1

アプリケーションの一部として矢印キーを使用しようとしています。ベスト プラクティスに従って、キー バインディングの使用に固執しました。矢印キーはキー型のイベントを生成しないので、この回答を採用しました。

しかし、私のアプリケーションには多くのコンポーネントがあり、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);
        }
    }    
}
4

2 に答える 2

4

デフォルトでJToolBarは、KeyStroke の UP/DOWN/LEFT/RIGHT のアクションを登録し、JToolBarに追加するとJFrame自動的にフォーカスが取得されるため、ルートペインにバインドしても何も表示されません (ツールバーが前のイベントをキャッチします)。

1 つの解決策は、JToolBarと をJButtonフォーカス不可にし、 をフォーカス可能JPanelにすることです (実際には 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);
        }
    }
}

getActionMap/getInputMapまた、あなたの への呼び出しを への単一の呼び出しに置き換えましたjavax.swing.JComponent.registerKeyboardAction(ActionListener, String, KeyStroke, int)

于 2013-06-11T16:45:35.050 に答える
1

この回答のアドバイスに従って、使用して問題を解決しました

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()));
    } 


}
于 2013-06-11T16:07:19.540 に答える