JFrame没有响应的KeyListener

Tom*_*mek 78 java swing keylistener jframe

我正在尝试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"); }
});
Run Code Online (Sandbox Code Playgroud)

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

我当时认为这可能是因为焦点不在于JFrame
,所以他们KeyListener没有收到任何事件.但是,我很确定它是.

有什么东西我错过了吗?

Pet*_*ter 128

如果您不想在每个组件上注册一个监听器,
您可以将自己的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • KeyboardFocusManager是应用程序范围的,如果你有多帧,你会遇到麻烦吗? (4认同)
  • 所以这应该可以工作,例如: foreach("focusable components in the frame" as _){ _.addkeylistener(frameKeylistener);} (2认同)

bru*_*nde 46

您必须将keyListener添加到您需要的每个组件.只有具有焦点的组件才会发送这些事件.例如,如果JFrame中只有一个TextBox,则该TextBox具有焦点.因此,您还必须将KeyListener添加到此组件.

过程是一样的:

myComponent.addKeyListener(new KeyListener ...);
Run Code Online (Sandbox Code Playgroud)

注意:某些组件不像JLabel那样具有可聚焦性.

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

myComponent.setFocusable(true);
Run Code Online (Sandbox Code Playgroud)

  • 是的,你是对的,当程序启动时,你可以稍微看到焦点在按钮 A 上。为每个按钮添加一个键盘监听器解决了这个问题。这有点奇怪,我认为向 JFrame 添加密钥侦听器会起作用,但我想不会。谢谢! (2认同)

Nat*_*han 16

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);
Run Code Online (Sandbox Code Playgroud)


Tom*_*ine 10

KeyListener是低级别,仅适用于单个组件.尽管尝试使其更有用,但JFrame创建了许多组件组件,最明显的是内容窗格.JComboBoxUI通常也以类似的方式实现.

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

有关您应该做什么的详细信息,请参阅我在应用程序范围的键盘快捷方式上的答案- Java Swing.


小智 10

我遇到了同样的问题,直到我读到真正的问题是关于FOCUS你的JFrame已经添加了Listeners但是Tour框架永远不会聚焦,因为你的JFrame中有很多组件也是可聚焦的,所以试试:

JFrame.setFocusable(true);
Run Code Online (Sandbox Code Playgroud)

祝好运

  • 我发现只有在我使用JFrame上的内容之后才能使用,然后KeyListener不再响应 (2认同)

小智 8

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;
}
Run Code Online (Sandbox Code Playgroud)