为什么Jtoolbar会破坏我的keyBindings?

时间:2013-06-11 15:12:33

标签: java swing jframe jpanel key-bindings

我一直在尝试使用箭头键作为我的应用程序的一部分。按照最佳实践,我坚持使用键绑定。我发现arow键不会产生键入事件,所以我使用了这个answer

但是,我的应用程序有许多组件,我发现如果我的JFrame中有一个JToolbar,则前一个链接中的方法不再有效。为什么这样,我如何使用JToolbar并使用键绑定?

这是SSCCE

public class ArrowTest extends JFrame {

    public static void main(final String[] args){
        final ArrowTest at = new ArrowTest();
        at.setSize(100,200);

        final JPanel jp = new JPanel();
        jp.setBackground(Color.BLUE);
        at.getContentPane().add(jp);
        final JToolBar toolbar = new JToolBar();
        toolbar.add(new JButton());
        //at.add(toolbar);
        at.setVisible(true);
    }

    public ArrowTest() {
        super();    
        this.getContentPane().setLayout(new GridBagLayout());    
        this.getContentPane().setBackground(Color.BLACK);    
        this.setKeyBindings();
    }

    public void setKeyBindings() {

        final int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;    
        final ActionMap actionMap = this.getRootPane().getActionMap();
        final InputMap inputMap = this.getRootPane().getInputMap(condition);

        for (final Direction direction : Direction.values()) {
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V,0), direction.getText());
            inputMap.put(direction.getKeyStroke(), direction.getText());
            actionMap.put(direction.getText(), new MyArrowBinding(direction.getText()));
        }

    }

    enum Direction {
        UP("Up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)),
        DOWN("Down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)),
        LEFT("Left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)),
        RIGHT("Right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));

        Direction(final String text, final KeyStroke keyStroke) {
            this.text = text;
            this.keyStroke = keyStroke;
        }
        private String text;
        private KeyStroke keyStroke;

        public String getText() {
            return text;
        }

        public KeyStroke getKeyStroke() {
            return keyStroke;
        }

        @Override
        public String toString() {
            return text;
        }
    }

    private class MyArrowBinding extends AbstractAction {

        private static final long serialVersionUID = -6904517741228319299L;

        public MyArrowBinding(final String text) {
            super(text);
            putValue(ACTION_COMMAND_KEY, text);
        }

        @Override
        public void actionPerformed(final ActionEvent e) {
            final String actionCommand = e.getActionCommand();
            System.out.println("Key Binding: " + actionCommand);
        }
    }    
}

2 个答案:

答案 0 :(得分:4)

默认情况下,JToolBar会为KeyStroke的向上/向下/向左/向右注册一个动作,而您添加到JToolBar的{​​{1}}会自动抓取焦点,因此您不会绑定到rootpane时会看到任何内容(工具栏会在你之前捕获事件)。

一种解决方案是让JFrameJToolBar无法集中,让您的JButton可以集中精力(实际上您可以离开JPanel和{{1请求专注于您的面板,但这也意味着您必须处理面板的焦点管理):

JToolBar

我也通过拨打JButton

来取代您对import java.awt.Color; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JToolBar; import javax.swing.KeyStroke; public class ArrowTest extends JFrame { public static void main(final String[] args) { final ArrowTest at = new ArrowTest(); at.setSize(100, 200); final JPanel jp = new JPanel(); jp.setBackground(Color.BLUE); jp.setFocusable(true); at.getContentPane().add(jp); final JToolBar toolbar = new JToolBar(); JButton comp = new JButton(); toolbar.add(comp); at.add(toolbar); at.setVisible(true); } public ArrowTest() { super(); this.getContentPane().setLayout(new GridBagLayout()); this.getContentPane().setBackground(Color.BLACK); this.setKeyBindings(); } public void setKeyBindings() { for (final Direction direction : Direction.values()) { MyArrowBinding binding = new MyArrowBinding(direction.getText()); getRootPane().registerKeyboardAction(binding, direction.getText(), direction.getKeyStroke(), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); } } enum Direction { UP("Up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)), DOWN("Down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)), LEFT("Left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)), RIGHT("Right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0)); Direction(final String text, final KeyStroke keyStroke) { this.text = text; this.keyStroke = keyStroke; } private String text; private KeyStroke keyStroke; public String getText() { return text; } public KeyStroke getKeyStroke() { return keyStroke; } @Override public String toString() { return text; } } private class MyArrowBinding extends AbstractAction { private static final long serialVersionUID = -6904517741228319299L; public MyArrowBinding(final String text) { super(text); putValue(ACTION_COMMAND_KEY, text); } @Override public void actionPerformed(final ActionEvent e) { final String actionCommand = e.getActionCommand(); System.out.println("Key Binding: " + actionCommand); } } } 的来电

答案 1 :(得分:1)

按照answer中的建议,我使用

解决了这个问题
public void setKeyBindings() {

    final int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;    
    final ActionMap actionMap = this.getRootPane().getActionMap();
    final InputMap inputMap = this.getRootPane().getInputMap(condition);

    for (final Direction direction : Direction.values()) {
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V,0), direction.getText());
        inputMap.put(direction.getKeyStroke(), direction.getText());
        actionMap.put(direction.getText(), new MyArrowBinding(direction.getText()));
    }

    condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;

    actionMap = toolbar.getActionMap();
    inputMap = toolbar.getInputMap(condition);


    for (final Direction direction : Direction.values()) {
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V,0), direction.getText());
        inputMap.put(direction.getKeyStroke(), direction.getText());
        actionMap.put(direction.getText(), new MyArrowBinding(direction.getText()));
    } 


}