Keylistener no trabaja para JPanel

Estoy tratando de hacer algo cuando se presiona una de las teclas de flecha con KeyListener en mi clase de JPanel. Aquí está mi código:

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

Mi método principal agrega una nueva instancia de este panel a un marco y lo muestra. ¿Debo agregar el keylistener al JFrame? En mi caso, esto sería difícil e ineficiente, por lo que me gustaría hacer que funcione con este JPanel si es posible. ¿Alguien sabe lo que estoy haciendo mal?

EDITAR: Código de enlaces clave que tampoco funciona:

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

¿Puede alguien decirme por qué esto tampoco funciona? (Mi segundo oyente de acción es para otras cosas necesarias para mi juego)

Si busca este problema, verá que se le preguntó y se ha resuelto muchas veces.

  • Los KeyListeners deben estar en el componente enfocado para trabajar. Una solución es darle el foco a tu componente después de hacerlo enfocable.
  • Sin embargo, es mejor utilizar una combinación de teclas. Google el tutorial sobre esto.

Por favor, eche un vistazo a mi respuesta a esta pregunta para obtener más información sobre esto, incluidos muchos de los detalles sangrientos.

Como referencia, he creado un ejemplo utilizando su enfoque; mientras funciona, también sugiere un problema de foco en otra parte de tu código. Los enlaces clave evitan esto, como se muestra aquí .

Adición: Aquí está mi enlace de clave de trabajo.

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

SSCCE original:

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

Tuve que hacer dos cosas: agregué comp.setFocusable (verdadero); a la comp del componente que escucha los eventos clave, y agregué comp.requestFocus (); a cada acción que causó que el comp pierda el foco.