Java 密钥绑定不起作用

Java 密钥绑定不起作用,java,swing,key-bindings,Java,Swing,Key Bindings,我让JButton通过ActionListener执行一些操作。在我尝试使用Action绑定一个键盘快捷键(如下所示)后,鼠标点击按钮可以工作,但对键盘并没有反应 前代码 在面板中创建的按钮,添加了actionListener private FooActionListener actionListener=new FooActionListener(); buttonLeft=新按钮(“左”); addActionListener(actionListener); 然后,在主类之外的FooA

我让JButton通过ActionListener执行一些操作。在我尝试使用Action绑定一个键盘快捷键(如下所示)后,鼠标点击按钮可以工作,但对键盘并没有反应

前代码 在面板中创建的按钮,添加了actionListener

private FooActionListener actionListener=new FooActionListener();
buttonLeft=新按钮(“左”);
addActionListener(actionListener);
然后,在主类之外的FooActionListener类中执行actionPerformed方法:

public void actionPerformed(ActionEvent e){
对象源=e.getSource();
if(source==buttonLeft){thing.move(Direction.LEFT);}
}
暗号
最后一个字符串leftText=“Left”;
左最终操作=新抽象操作(){
@凌驾
已执行的公共无效操作(操作事件e){
东西。移动(方向。左);
}
};
buttonLeft=新的JButton(左);
按钮left.setText(leftText);
KeyStroke keyLeft=击键.getKeyStroke(KeyEvent.VK_A,0);
buttonLeft.getInputMap(当在聚焦窗口中时buttonLeft.put).put(向左键,
“左”);
按钮Left.getActionMap().put(“左”,左);

更新:我不太确定新代码是否真的能在鼠标上正常运行。让我们假设该对象通过单击移动25个像素,并且在原始代码中确实如此。但是,对于新的操作,它似乎在每次单击时移动两次甚至三次,这表明某个操作有一些奇怪的行为。

按钮可能会吸引你,但是,我会稍微改变一下

因为您已经正确地使用了
操作
,所以您的移动逻辑基本上已经集中化了

我只是将映射应用到主容器

public class TestKeybindings01 {

    public static void main(String[] args) {
        new TestKeybindings01();
    }

    public TestKeybindings01() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JLabel label;
        private JButton left;
        private JButton right;

        public TestPane() {

            label = new JLabel("Make a choice");
            label.setHorizontalAlignment(JLabel.CENTER);

            LeftAction leftAction = new LeftAction(label);
            RightAction rightAction = new RightAction(label);

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "left");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "right");

            ActionMap am = getActionMap();
            am.put("left", leftAction);
            am.put("right", rightAction);

            left = new JButton(leftAction);
            right = new JButton(rightAction);

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.gridwidth = 2;
            gbc.anchor = GridBagConstraints.CENTER;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            add(label, gbc);

            gbc.gridy++;
            gbc.gridwidth = 1;
            add(left, gbc);
            gbc.gridx++;
            add(right, gbc);


        }

    }

    public abstract class AbstractDirectionAction extends AbstractAction {

        private JLabel label;

        public AbstractDirectionAction(JLabel label) {
            this.label = label;
        }

        public JLabel getLabel() {
            return label;
        }

        public void setDirection(String text) {
            getLabel().setText(text);
        }

    }

    public class LeftAction extends AbstractDirectionAction {

        public LeftAction(JLabel label) {
            super(label);
            putValue(NAME, "<<");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            setDirection("Left");
        }

    }

    public class RightAction extends AbstractDirectionAction {

        public RightAction(JLabel label) {
            super(label);
            putValue(NAME, ">>");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            setDirection("Right");
        }

    }

}
公共类TestKeybindings01{
公共静态void main(字符串[]args){
新的TestKeybindings01();
}
公共TestKeybindings01(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
}
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(新的BorderLayout());
frame.add(newtestpane());
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
});
}
公共类TestPane扩展了JPanel{
私人标签;
私人按钮左;
私权;
公共测试窗格(){
标签=新的JLabel(“做出选择”);
标签设置水平对齐(JLabel.CENTER);
LeftAction LeftAction=新的LeftAction(标签);
RightAction RightAction=新的RightAction(标签);
InputMap im=getInputMap(在聚焦窗口中时);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A,0),“left”);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D,0),“right”);
ActionMap am=getActionMap();
am.put(“左”,左动作);
am.put(“正确”,正确行动);
左=新的JButton(左操作);
右=新的JButton(右操作);
setLayout(新的GridBagLayout());
GridBagConstraints gbc=新的GridBagConstraints();
gbc.gridx=0;
gbc.gridy=0;
gbc.gridwidth=2;
gbc.anchor=GridBagConstraints.CENTER;
gbc.fill=GridBagConstraints.HORIZONTAL;
添加(标签,gbc);
gbc.gridy++;
gbc.gridwidth=1;
添加(左,gbc);
gbc.gridx++;
添加(右,gbc);
}
}
公共抽象类AbstractDirectionAction扩展了AbstractAction{
私人标签;
公共抽象定向操作(JLabel标签){
this.label=标签;
}
公共JLabel getLabel(){
退货标签;
}
公共void setDirection(字符串文本){
getLabel().setText(文本);
}
}
公共类LeftAction扩展了AbstractDirectionAction{
公共LeftAction(JLabel标签){
超级(标签);
putValue(名称“”);
}
@凌驾
已执行的公共无效操作(操作事件e){
设定方向(“右”);
}
}
}

您能否详细说明这些映射的含义?另外,检查问题的更新,看看这是否暗示了什么。那么这个EventQueue.invokeLater业务是关于什么的呢?按钮实现可能正在“吸收”关键事件,这可能是它对助记符支持的一部分,阻止它为关键绑定引发事件。我能想到的重复发生这样的事件的唯一原因是你按下了键。之所以出现
EventQueue.invokeLater
,是因为Swing是一个单线程API,对UI的所有更新都必须在事件调度线程中进行。当您执行
main
时,可以保证您没有使用EDTA进行重复操作,我现在说的是鼠标点击。我使用与原始代码完全相同的鼠标单击,但它似乎在同一次单击中调用thing.move方法两次。有什么方法可以调试它吗?给你的应用程序添加一些诊断程序,并确定该操作是否执行了一次以上。@theUg