java - JFrame的无响应KeyListener
我正在尝试为我的KeyListener实现JFrame.在构造函数上,我正在使用此代码:
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"); }
});
当我运行它时,JFrame消息出现在我的控制台中。 但是,当我按下一个键时,我没有得到任何其他消息,就好像KeyListener甚至没有。
我当时认为可能是因为焦点不在于JFrame
所以他们KeyListener没有收到任何活动。 但是,我很确定它是。
有什么东西我错过了吗?
12个解决方案
125 votes
如果您不想在每个组件上注册侦听器,
你可以添加自己的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);
}
}
Peter answered 2019-04-24T11:05:03Z
46 votes
您必须将keyListener添加到您需要的每个组件。 只有具有焦点的组件才会发送这些事件。 例如,如果JFrame中只有一个TextBox,则该TextBox具有焦点。 因此,您还必须将KeyListener添加到此组件。
过程是一样的:
myComponent.addKeyListener(new KeyListener ...);
注意:某些组件不像JLabel那样具有可聚焦性。
要将它们设置为可聚焦,您需要:
myComponent.setFocusable(true);
bruno conde answered 2019-04-24T11:04:31Z
15 votes
InputMaps和ActionMaps旨在捕获组件及其所有子组件或整个窗口的关键事件。 这是通过JComponent.getInputMap()中的参数控制的。 有关文档,请参见如何使用键绑定。
这种设计的优点在于,人们可以挑选和选择哪些关键笔划对于监控是重要的,并且基于这些关键笔划触发不同的操作。
当在窗口中的任何位置按下转义键时,此代码将在JFrame上调用dispose()。 JFrame不是从JComponent派生的,因此您必须使用JFrame中的另一个组件来创建键绑定。 内容窗格可能是这样的组件。
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);
Nathan answered 2019-04-24T11:05:43Z
10 votes
KeyListener是低级别,仅适用于单个组件。 尽管尝试使其更加可用JFrame创建了许多组件组件,但最明显的是内容窗格。 JComboBox UI也经常以类似的方式实现。
值得注意的是,鼠标事件以一种与关键事件略有不同的奇怪方式工作。
有关您应该做什么的详细信息,请参阅我在应用程序范围的键盘快捷方式上的答案 - Java Swing。
Tom Hawtin - tackline answered 2019-04-24T11:06:23Z
10 votes
我遇到了同样的问题,直到我读到真正的问题是关于FOCUS你的JFrame已经添加了Listeners但是Tour框架永远不会聚焦,因为你的JFrame中有很多组件也是可聚焦的,所以试试:
JFrame.setFocusable(true);
祝好运
Jérôme Verstrynge answered 2019-04-24T11:06:52Z
8 votes
Deion(以及其他任何提出类似问题的人),您可以使用上面的Peter代码,但不是打印到标准输出,而是测试密钥代码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;
}
Daves answered 2019-04-24T11:07:18Z
4 votes
为了捕获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;
}
}
Hubert Kauker answered 2019-04-24T11:07:44Z
2 votes
嗯..你的构造函数是什么类的? 可能是一些扩展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);
}
}
Touko answered 2019-04-24T11:08:18Z
2 votes
这应该有所帮助
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");
}
});
Rahul answered 2019-04-24T11:08:44Z
1 votes
我一直有同样的问题。 我按照Bruno给你的建议,发现只需将KeyListener添加到JFrame中的“第一个”按钮(即左上角)就可以了。 但我同意你的意见,这是一种令人不安的解决方案。 所以我摆弄着并发现了一种更简洁的方法来解决它。 只需添加该行
myChildOfJFrame.requestFocusInWindow();
在创建了JFrame子类的实例并将其设置为可见之后,在main方法中。
pocketdora answered 2019-04-24T11:09:17Z
-2 votes
大声笑....所有你要做的就是确保
addKeyListener(本);
正确放置在您的代码中。
Chris answered 2019-04-24T11:09:57Z
-2 votes
您可以让自定义JComponents将其父JFrame设置为可焦点。
只需添加一个构造函数并传入JFrame即可。 然后在paintComponent中调用setFocusable()。
这样,无论是否按下其他组件,JFrame将始终接收KeyEvents。
Denizen answered 2019-04-24T11:10:36Z