Keylistener不能用于JPanel

我正试图做一些事情,当我的JPanel类中的KeyListener按下其中一个箭头键。 这是我的代码:

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

我的主要方法是将这个面板的一个新的实例添加到一个框架并显示它。 我是否需要将关键字添加到JFrame? 在我的情况下,这将是困难和低效的,所以我想尽可能使它与这个JPanel一起工作。 任何人都知道我在做什么错了?

编辑:键绑定代码不起作用:

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

有人可以告诉我为什么这不工作吗? (我的第二个动作侦听器是为了我的游戏需要的其他东西)

如果你search这个问题,你会发现它被问及已被多次解决。

  • KeyListeners需要在关注的组件上工作。 一种解决scheme是在首先使其可聚焦之后给予组件焦点。
  • 长远来说,更好的办法是使用键绑定。 谷歌在这个教程。

请看看我对这个问题的更多回答,包括许多血淋淋的细节。

作为参考,我已经用你的方法创build了一个例子。 虽然它的工作,它也表明在你的代码其他地方的焦点问题。 键绑定避免这一点,如图所示。

附录:这是我的工作键绑定。

 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:

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

我不得不做两件事:我添加了comp.setFocusable(true); 到监听关键事件的组件comp,我添加了comp.requestFocus(); 给每一个导致比赛失去焦点的动作。