Java JFrame 的无响应 KeyListener
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/286727/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unresponsive KeyListener for JFrame
提问by Tomek
I'm trying to implement a KeyListener
for my JFrame
. On the constructor, I'm using this code:
我正在尝试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"); }
});
When I run it, the test
message comes up in my console. However, when I press a key, I don't get any of the other messages, as if the KeyListener
was not even there.
当我运行它时,test
消息出现在我的控制台中。但是,当我按下一个键时,我没有收到任何其他消息,就好像它KeyListener
根本不存在一样。
I was thinking that it could be because the focus is not on the JFrame
and so they KeyListener
doesn't receive any events. But, I'm pretty sure it is.
我在想这可能是因为重点不在JFrame
,所以他们KeyListener
没有收到任何事件。但是,我很确定它是。
Is there something that I am missing?
有什么我想念的吗?
采纳答案by bruno conde
You must add your keyListener to every component that you need. Only the component with the focus will send these events. For instance, if you have only one TextBox in your JFrame, that TextBox has the focus. So you must add a KeyListener to this component as well.
您必须将 keyListener 添加到您需要的每个组件中。只有具有焦点的组件才会发送这些事件。例如,如果您的 JFrame 中只有一个 TextBox,则该 TextBox 具有焦点。因此,您还必须向该组件添加一个 KeyListener。
The process is the same:
过程是一样的:
myComponent.addKeyListener(new KeyListener ...);
Note: Some components aren't focusable like JLabel.
注意:有些组件不像 JLabel 那样可聚焦。
For setting them to focusable you need to:
要将它们设置为可聚焦,您需要:
myComponent.setFocusable(true);
回答by Touko
Hmm.. what class is your constructor for? Probably some class extending JFrame? The window focus should be at the window, of course but I don't think that's the problem.
嗯.. 你的构造函数是什么类的?可能是一些扩展 JFrame 的类?窗口焦点当然应该在窗口上,但我认为这不是问题所在。
I expanded your code, tried to run it and it worked - the key presses resulted as print output. (run with Ubuntu through Eclipse):
我扩展了您的代码,尝试运行它并且它起作用了 - 按键结果作为打印输出。(通过 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);
}
}
回答by Tom Hawtin - tackline
KeyListener
is low level and applies only to a single component. Despite attempts to make it more usable JFrame
creates a number of component components, the most obvious being the content pane. JComboBox
UI is also often implemented in a similar manner.
KeyListener
是低级别的,仅适用于单个组件。尽管试图使其更有用,但JFrame
创建了许多组件组件,最明显的是内容窗格。JComboBox
UI 也经常以类似的方式实现。
It's worth noting the mouse events work in a strange way slightly different to key events.
值得注意的是,鼠标事件的工作方式与按键事件略有不同。
For details on what you should do, see my answer on Application wide keyboard shortcut - Java Swing.
有关您应该做什么的详细信息,请参阅我对应用程序范围的键盘快捷键 - Java Swing 的回答。
回答by Tom Hawtin - tackline
I got the same problem until i read that the real problem is about FOCUS the your JFrame has already added Listeners but tour frame is never on Focus because you got a lot of components inside your JFrame that also are focusable so try:
我遇到了同样的问题,直到我读到真正的问题是关于 FOCUS,你的 JFrame 已经添加了监听器,但 Tour 框架从来没有在 Focus 上,因为你的 JFrame 中有很多组件也是可聚焦的,所以尝试:
JFrame.setFocusable(true);
Good Luck
祝你好运
回答by Peter
If you don't want to register a listener on every component,
you could add your own KeyEventDispatcher
to the KeyboardFocusManager
:
如果您不想在每个组件上注册一个侦听器,
您可以将自己的添加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);
}
}
回答by pocketdora
I have been having the same problem. I followed Bruno's advice to you and found that adding a KeyListener just to the "first" button in the JFrame (ie, on the top left) did the trick. But I agree with you it is kind of an unsettling solution. So I fiddled around and discovered a neater way to fix it. Just add the line
我一直有同样的问题。我遵循了布鲁诺的建议,发现将 KeyListener 添加到 JFrame 中的“第一个”按钮(即左上角)可以解决问题。但我同意你的看法,这是一个令人不安的解决方案。所以我摆弄了一下,发现了一种更简洁的方法来修复它。只需添加行
myChildOfJFrame.requestFocusInWindow();
to your main method, after you've created your instance of your subclass of JFrame and set it visible.
在您创建 JFrame 子类的实例并将其设置为可见之后,转到您的主方法。
回答by Daves
Deion (and anyone else asking a similar question), you could use Peter's code above but instead of printing to standard output, you test for the key code PRESSED, RELEASED, or TYPED.
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;
}
回答by Hubert Kauker
in order to capture key events of ALL text fields in a JFrame, one can employ a key event post processor. Here is a working example, after you add the obvious includes.
为了捕获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;
}
}
回答by Chris
lol .... all you have to do is make sure that
大声笑 .... 你所要做的就是确保
addKeyListener(this);
addKeyListener(this);
is placed correctly in your code.
正确放置在您的代码中。
回答by Denizen
You could have custom JComponents set their parent JFrame focusable.
您可以让自定义 JComponent 将其父 JFrame 设置为可聚焦。
Just add a constructor and pass in the JFrame. Then make a call to setFocusable() in paintComponent.
只需添加一个构造函数并传入 JFrame。然后在paintComponent 中调用setFocusable()。
This way the JFrame will always receive KeyEvents regardless of whether other components are pressed.
这样,无论其他组件是否被按下,JFrame 将始终接收 KeyEvents。