JFrame的无响应KeyListener

我试图为我的JFrame实现一个KeyListener 。 在构造函数上,我使用这个代码:

 System.out.println("test"); addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { System.out.println( "tester"); } public void keyReleased(KeyEvent e) { System.out.println("2test2"); } public void keyTyped(KeyEvent e) { System.out.println("3test3"); } }); 

当我运行它时, test消息出现在我的控制台中。 但是,当我按一个键,我没有得到任何其他的消息,就像KeyListener甚至没有。

我想这可能是因为焦点不在JFrame
所以他们KeyListener不会收到任何事件。 但是,我很确定这是。

有什么我失踪了吗?

您必须将您的keyListener添加到您需要的每个组件。 只有具有焦点的组件才会发送这些事件。 例如,如果您的JFrame中只有一个文本框,则该文本框具有焦点。 所以你也必须添加一个KeyListener到这个组件。

过程是一样的:

 myComponent.addKeyListener(new KeyListener ...); 

注意:某些组件不像JLabel那样可聚焦。

为了将它们设置为可聚焦的,您需要:

 myComponent.setFocusable(true); 

如果你不想在每个组件上注册一个监听器,
您可以将您自己的KeyEventDispatcher添加KeyboardFocusManager

 public class MyFrame extends JFrame { private class MyDispatcher implements KeyEventDispatcher { @Override public boolean dispatchKeyEvent(KeyEvent e) { if (e.getID() == KeyEvent.KEY_PRESSED) { System.out.println("tester"); } else if (e.getID() == KeyEvent.KEY_RELEASED) { System.out.println("2test2"); } else if (e.getID() == KeyEvent.KEY_TYPED) { System.out.println("3test3"); } return false; } } public MyFrame() { add(new JTextField()); System.out.println("test"); KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); manager.addKeyEventDispatcher(new MyDispatcher()); } public static void main(String[] args) { MyFrame f = new MyFrame(); f.pack(); f.setVisible(true); } } 

InputMaps和ActionMaps被devise用来捕获组件,它及其所有子组件或整个窗口的关键事件。 这是通过JComponent.getInputMap()中的参数控制的。 有关文档,请参阅如何使用密钥绑定 。

这种devise的美妙之处在于,人们可以select哪些击键是重要的监视,并根据这些击键来触发不同的动作。

此代码将在窗口中的任何位置点击转义键时调用JFrame上的dispose()。 JFrame不会从JComponent派生,因此您必须使用JFrame中的另一个组件来创build密钥绑定。 内容窗格可能是这样一个组件。

 InputMap inputMap; ActionMap actionMap; AbstractAction action; JComponent component; inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); actionMap = component.getActionMap(); action = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { dispose(); } }; inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "dispose"); actionMap.put("dispose", action); 

KeyListener是低级别的,仅适用于单个组件。 尽pipe试图使其更加可用,但JFrame创build了许多组件组件,最明显的就是内容窗格。 JComboBox UI也经常以类似的方式实现。

值得注意的是,鼠标事件以一种奇怪的方式工作,与关键事件略有不同。

有关您应该执行的操作的详细信息,请参阅应用程序范围键盘快捷键 – Java Swing中的我的回答。

我得到了同样的问题,直到我看到真正的问题是关于焦点你的JFrame已经添加了听众,但游览框架从来没有在焦点,因为你有很多组件内JFrame也是可以聚焦所以试试:

 JFrame.setFocusable(true); 

祝你好运

Deion(以及任何其他人提出类似的问题),你可以使用Peter的代码,而不是打印到标准输出,而是testing按键代码PRESSED,RELEASED或TYPED。

 @Override public boolean dispatchKeyEvent(KeyEvent e) { if (e.getID() == KeyEvent.KEY_PRESSED) { if (e.getKeyCode() == KeyEvent.VK_F4) { dispose(); } } else if (e.getID() == KeyEvent.KEY_RELEASED) { if (e.getKeyCode() == KeyEvent.VK_F4) { dispose(); } } else if (e.getID() == KeyEvent.KEY_TYPED) { if (e.getKeyCode() == KeyEvent.VK_F4) { dispose(); } } return false; } 

为了捕获JFrame中所有文本字段的关键事件,可以使用关键事件后处理器。 在添加明显的包含之后,以下是一个工作示例。

 public class KeyListenerF1Demo extends JFrame implements KeyEventPostProcessor { public static final long serialVersionUID = 1L; public KeyListenerF1Demo() { setTitle(getClass().getName()); // Define two labels and two text fields all in a row. setLayout(new FlowLayout()); JLabel label1 = new JLabel("Text1"); label1.setName("Label1"); add(label1); JTextField text1 = new JTextField(10); text1.setName("Text1"); add(text1); JLabel label2 = new JLabel("Text2"); label2.setName("Label2"); add(label2); JTextField text2 = new JTextField(10); text2.setName("Text2"); add(text2); // Register a key event post processor. KeyboardFocusManager.getCurrentKeyboardFocusManager() .addKeyEventPostProcessor(this); } public static void main(String[] args) { JFrame f = new KeyListenerF1Demo(); f.setName("MyFrame"); f.pack(); f.setVisible(true); } @Override public boolean postProcessKeyEvent(KeyEvent ke) { // Check for function key F1 pressed. if (ke.getID() == KeyEvent.KEY_PRESSED && ke.getKeyCode() == KeyEvent.VK_F1) { // Get top level ancestor of focused element. Component c = ke.getComponent(); while (null != c.getParent()) c = c.getParent(); // Output some help. System.out.println("Help for " + c.getName() + "." + ke.getComponent().getName()); // Tell keyboard focus manager that event has been fully handled. return true; } // Let keyboard focus manager handle the event further. return false; } } 

嗯..你的构造函数是什么类? 可能有些类扩展了JFrame? 窗口焦点应该在窗口,当然,但我不认为这是问题。

我扩大了你的代码,试图运行它,它的工作 – 键输出结果作为打印输出。 (通过Eclipse运行Ubuntu):

 public class MyFrame extends JFrame { public MyFrame() { System.out.println("test"); addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { System.out.println("tester"); } public void keyReleased(KeyEvent e) { System.out.println("2test2"); } public void keyTyped(KeyEvent e) { System.out.println("3test3"); } }); } public static void main(String[] args) { MyFrame f = new MyFrame(); f.pack(); f.setVisible(true); } } 

这应该有所帮助

  yourJFrame.setFocusable(true); yourJFrame.addKeyListener(new java.awt.event.KeyAdapter() { @Override public void keyTyped(KeyEvent e) { System.out.println("you typed a key"); } @Override public void keyPressed(KeyEvent e) { System.out.println("you pressed a key"); } @Override public void keyReleased(KeyEvent e) { System.out.println("you released a key"); } }); 

我一直有同样的问题。 我按照布鲁诺的build议给你,发现只要在JFrame(即左上angular)的“第一个”button上添加一个KeyListener就可以了。 但我同意你的看法,这是一个令人不安的解决scheme。 所以我摆弄,发现一个更好的方法来解决它。 只需添加该行

 myChildOfJFrame.requestFocusInWindow(); 

在创build了JFrame的子类的实例并将其设置为可见之后,将其添加到主方法中。

大声笑….所有你需要做的是确保

addKeyListener(本);

被正确放置在您的代码中。

您可以让自定义JComponents将其父级JFrame设置为可聚焦的。

只需添加一个构造函数并传递给JFrame。 然后调用paintComponent中的setFocusable()。

这样,无论是否按下其他组件,JFrame都将始终接收KeyEvent。