Java 单击JButton后,键盘输入在Swing应用程序(计算器)中停止工作

Java 单击JButton后,键盘输入在Swing应用程序(计算器)中停止工作,java,swing,jbutton,calculator,keylistener,Java,Swing,Jbutton,Calculator,Keylistener,我正在用Swing做一个计算器。到目前为止,我已经创建了一个GUI,它由一个带有BorderLayout的JFrame组成,在它的中心我放置了一个JPanel,它有一个JLabel(表示计算器的屏幕)和一些JButton(表示键) 我希望计算器能够直接从键盘接收输入,因此我将addKeyListener方法包含在扩展JFrame的类中,并将对实现KeyListener的类的对象的引用作为参数 当我运行应用程序时,它接受键盘输入,直到我单击其中一个JButton。在那之后,使用键盘就不起作用了 我

我正在用Swing做一个计算器。到目前为止,我已经创建了一个GUI,它由一个带有BorderLayout的JFrame组成,在它的中心我放置了一个JPanel,它有一个JLabel(表示计算器的屏幕)和一些JButton(表示键)

我希望计算器能够直接从键盘接收输入,因此我将addKeyListener方法包含在扩展JFrame的类中,并将对实现KeyListener的类的对象的引用作为参数

当我运行应用程序时,它接受键盘输入,直到我单击其中一个JButton。在那之后,使用键盘就不起作用了

我怀疑这个问题与焦点有关,但我不能通过单击应用程序上的任意位置来解决这个问题。我添加了以下代码:

setFocusable(true);
到JFrame,但它没有帮助。我已经读到使用键绑定可能是比使用KeyListener更好的选择,但我并不确定这种方法。

Swing组件是轻量级的,并且可以使用,
KeyListener
s用于重量级的AWT组件。与Swing组件混合时会出现焦点问题。因此,我建议改为
KeyBindings
(但我知道您听说过它们)。您可以使用它们,例如:

final JButton b=..;

//method to add keybindings to a JComponent ie JButton,JPanel,JTextField etc
private void addKeyBindings(JComponent jc) {

    //not the getInputMap(..) call it could also be JComponent.WHEN_FOCUSED etc
    jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("D"), "D pressed");

    jc.getActionMap().put("D pressed", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            //do something when d is pressed
            b.doClick();
        }
    });
}

一般来说,一个非常黑客的解决方案是,每当焦点丢失时(如单击按钮后等),对侦听器所连接的组件调用
requestFocusInWindow()

这是另一种黑客方法,但是,您可以在创建JButton时更改其属性,使其无法首先获得焦点,即:

myJbutton.setFocusable(false);

这对我来说很有效。

//当按下d时做些什么
==需要添加
JButton#doClick()
@mKorbel very true+1从技术上讲,
KeyListener
不限于重量级组件,但它确实存在焦点问题-即注册的组件必须具有焦点才能接收关键事件,密钥绑定API可以用来克服这些问题。但是,+1用于密钥绑定,非常感谢。我决定使用你的“黑客解决方案”,因为它对我来说简单多了。还感谢您对键绑定的解释。这不是一个非常好的主意:这会使键盘无法访问按钮,从而违反可用性最佳实践(所有交互都必须通过鼠标和键盘实现)