2013-05-13 30 views
6

Tôi đang cố gắng làm điều gì đó khi một trong các phím mũi tên được nhấn bằng cách sử dụng KeyListener trong lớp JPanel của tôi. Đây là mã của tôi:Keylistener không hoạt động với JPanel

public class TestPanel extends JPanel implements KeyListener{ 

    public TestPanel(){ 
     this.addKeyListener(this); 
     this.setFocusable(true); 
     this.requestFocusInWindow(); 
    } 

    public void keyPressed(KeyEvent e) { 
     if (e.getKeyCode() == KeyEvent.VK_RIGHT) { 
      System.out.println("Right"); 

     } 

     if (e.getKeyCode() == KeyEvent.VK_LEFT) { 
      System.out.println("Left"); 
     } 

    } 

    public void keyTyped(KeyEvent e) {} 
    public void keyReleased(KeyEvent e) {} 
} 

Phương pháp chính của tôi thêm một trường hợp mới của bảng này vào khung và hiển thị nó. Tôi có cần phải thêm keylistener vào JFrame không? Trong trường hợp của tôi, điều này sẽ khó khăn và không hiệu quả, vì vậy tôi muốn làm cho nó hoạt động với JPanel này nếu có thể. Có ai biết tôi đang làm gì sai không?

EDIT: Key Bindings mã mà không làm việc, hoặc:

public class GamePanel extends JPanel implements ActionListener{ 

//Constructor 
public GamePanel(){ 

    setupKeyBinding(); 
    this.setFocusable(true); 
    this.requestFocusInWindow(); 


} 

private void setupKeyBinding() { 
    int condition = JComponent.WHEN_IN_FOCUSED_WINDOW; 
    InputMap inMap = getInputMap(condition); 
    ActionMap actMap = getActionMap(); 

    inMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "Left"); 
    actMap.put("Left", new leftAction()); 
} 

private class leftAction extends AbstractAction { 

     public void actionPerformed(ActionEvent e) { 
      System.out.println("test"); 
     } 
} 

public void actionPerformed(ActionEvent e) { 
    //some other game info 
} 
} 

Có thể ai đó cho tôi biết lý do tại sao việc doesnt này một trong hai? (người nghe hành động thứ hai của tôi dành cho những thứ khác cần thiết cho trò chơi của tôi)

+0

Một ý tưởng khác có thể là tạo một lớp bên trong và sử dụng một cái gì đó như: "this.addKeyListener (lớp bên trong/lớp bên trong vô danh);" – ObedMarsh

+0

có thể trùng lặp của [java keylistener not called] (http://stackoverflow.com/questions/8482268/java-keylistener-not-called) –

Trả lời

9

Nếu bạn tìm kiếm vấn đề này, bạn sẽ thấy rằng nó được hỏi và đã được giải quyết nhiều lần.

  • Máy ghi âm cần phải nằm trên thành phần được tập trung để hoạt động. Một giải pháp là cung cấp cho thành phần của bạn sự tập trung sau khi đầu tiên làm cho nó tập trung.
  • Tuy nhiên, tốt hơn là nên sử dụng Khóa chính. Google hướng dẫn về điều này.

Vui lòng xem câu trả lời của tôi cho this question để biết thêm về điều này, bao gồm nhiều chi tiết đẫm máu.

+0

Cảm ơn, tôi sẽ xem xét các ràng buộc chính, nhưng đối với vấn đề này tôi đã xem xét nhiều các giải pháp và không thể nhìn thấy những gì tôi đang làm khác nhau. Tôi nghĩ rằng tôi đã làm như vậy bằng cách sử dụng requestFocusInWindow() – user2373733

+3

Hành vi tập trung thay đổi theo nền tảng; hơn nữa, một 'KeyListener' sẽ dễ vỡ trong vấn đề này nếu có _any_ các thành phần có thể lấy nét khác. – trashgod

+0

@ user2373733 Các ràng buộc chính là cách để đi. Chỉ cần thả KeyListener của bạn: nó sẽ giúp bạn tiết kiệm thời gian và tránh các lỗi trong tương lai. –

4

Để tham khảo, tôi đã tạo một ví dụ sử dụng cách tiếp cận của bạn; trong khi nó hoạt động, nó cũng cho thấy một vấn đề tập trung ở nơi khác trong mã của bạn. Key Bindings tránh điều này, như được hiển thị here.

Hợp đồng bổ sung: Đây là ràng buộc khóa làm việc của tôi.

private static class TestPanel extends JPanel { 

    private static final String LEFT = "Left"; 
    private Action left = new AbstractAction(LEFT) { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      System.out.println(LEFT); 
     } 
    }; 
    private static final String RIGHT = "Right"; 
    private Action right = new AbstractAction(RIGHT) { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      System.out.println(RIGHT); 
     } 
    }; 

    public TestPanel() { 
     this.getInputMap().put(
      KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), LEFT); 
     this.getActionMap().put(LEFT, left); 
     this.getInputMap().put(
      KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), RIGHT); 
     this.getActionMap().put(RIGHT, right); 
    } 
} 

gốc SSCCE:

import java.awt.EventQueue; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

/** 
* @see https://stackoverflow.com/a/16531380/230513 
*/ 
public class Test { 

    private void display() { 
     JFrame f = new JFrame("Test"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(new TestPanel()); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    private static class TestPanel extends JPanel implements KeyListener { 

     public TestPanel() { 

      this.addKeyListener(this); 
      this.setFocusable(true); 
      this.requestFocusInWindow(); 
     } 

     @Override 
     public void keyPressed(KeyEvent e) { 
      if (e.getKeyCode() == KeyEvent.VK_RIGHT) { 
       System.out.println("Right"); 
      } 

      if (e.getKeyCode() == KeyEvent.VK_LEFT) { 
       System.out.println("Left"); 
      } 
     } 

     @Override 
     public void keyTyped(KeyEvent e) { 
     } 

     @Override 
     public void keyReleased(KeyEvent e) { 
     } 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Test().display(); 
      } 
     }); 
    } 
} 
+1

Ah cảm ơn, tôi không có ý tưởng những gì có thể được lấy tập trung. Tôi đặt tất cả các tấm khác của tôi được thêm vào khung của tôi để không tập trung trong khi thử nghiệm để đảm bảo không có gì can thiệp. Tôi đang cố gắng ra ràng buộc quan trọng bây giờ, mặc dù tôi đang gặp một chút rắc rối mới với rất nhiều công cụ này – user2373733

+0

Bạn có thể thử tối thiểu này [ví dụ] (http://stackoverflow.com/a/7457102/230513). – trashgod

+0

Vâng, đó là ví dụ mà tôi đã thử: ( – user2373733

1

tôi phải làm hai điều: tôi đã thêm comp.setFocusable (true); để comp thành phần lắng nghe các sự kiện quan trọng, và tôi đã thêm comp.requestFocus(); cho mỗi hành động gây ra comp để mất tập trung.

Các vấn đề liên quan