Keylistener funktioniert nicht für JPanel

Ich versuche etwas zu tun, wenn eine der Pfeiltasten mit dem KeyListener in meiner JPanel-class gedrückt wird. Hier ist mein Code:

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) {} } 

Meine Hauptmethode fügt einem Rahmen eine neue Instanz dieses Bereichs hinzu und zeigt sie an. Muss ich den Keylistener zum JFrame hinzufügen? In meinem Fall wäre das schwierig und ineffizient, also würde ich es gerne mit diesem JPanel machen, wenn möglich. Wer weiß, was ich falsch mache?

EDIT: Key Bindings Code, der auch nicht funktioniert:

 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 } } 

Kann mir jemand sagen, warum das auch nicht funktioniert? (Mein zweiter Action-Listener ist für andere Sachen, die für mein Spiel benötigt werden)

   

Wenn Sie dieses Problem suchen, werden Sie sehen, dass es gefragt wird und viele Male getriggers wurde.

  • KeyListeners müssen auf der fokussierten Komponente arbeiten. Eine Lösung besteht darin, die Komponente nach der Fokussierung zu fokussieren.
  • Besser ist es jedoch, Key Bindings zu verwenden. Google das Tutorial dazu.

Bitte casting Sie einen Blick auf meine Antwort auf diese Frage für mehr dazu, einschließlich vieler der blutigen Details.

Als Referenz habe ich ein Beispiel mit Ihrem Ansatz erstellt; Während es funktioniert, schlägt es auch ein Fokusproblem an anderer Stelle in Ihrem Code vor. Key Bindings vermeiden dies, wie hier gezeigt.

Nachtrag: Hier ist mein funktionierender Schlüssel verbindlich.

 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); } } 

Original 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(); } }); } } 

Ich musste zwei Dinge tun: Ich fügte comp.setFocusable (true) hinzu; zu der Komponente comp, die Schlüsselereignisse hört, und ich fügte comp.requestFocus () hinzu; zu jeder Aktion, die verursacht, dass comp den Fokus verliert.