Java Swing: Show pressed button when using corresponding keyboard button

混江龙づ霸主 提交于 2019-12-05 08:34:38

Using keyBindings (as @trashgod already mentioned) is the way to go. To get the exact same visual behaviour as if activating the button by space/enter (when it were focused)

  • implement actions that delegate to the button's default actions registered for pressed/released
  • needs binding to both pressed and released of the key to simulate
  • install the binding to the buttons's parent in its inputMap of type WHEN_ANCESTOR

In code:

// the delegating  action
public static class SimulateButtonAction extends AbstractAction {

    AbstractButton button;

    public SimulateButtonAction(AbstractButton model, String fire) {
        super(fire);
        this.button = model;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Action delegate = button.getActionMap().get(getName());
        delegate.actionPerformed(new ActionEvent(button, 
                ActionEvent.ACTION_PERFORMED, getName()));
    }

    public String getName() {
        return (String) getValue(Action.NAME);
    }

}

// example usage
JComponent content = new JPanel(new GridLayout(0, 5));
Action log = new AbstractAction() {

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("triggered: " + ((AbstractButton) e.getSource()).getText());
    }

};
String pressed = "pressed";
String released = "released";
ActionMap actionMap = content.getActionMap();
InputMap inputMap = content.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
String[] arrows = {"UP", "DOWN", "LEFT", "RIGHT"};
for (int i = 0; i < arrows.length; i++) {
    JButton button = new JButton(log);
    button.setAction(log);
    button.setText(arrows[i]);
    content.add(button);
    // simulate pressed
    String pressedKey = pressed + arrows[i];
    inputMap.put(KeyStroke.getKeyStroke(arrows[i]), pressedKey);
    actionMap.put(pressedKey, new SimulateButtonAction(button, pressed));
    String releasedKey = released + arrows[i];
    inputMap.put(KeyStroke.getKeyStroke(released + " " +arrows[i]), releasedKey);
    actionMap.put(releasedKey, new SimulateButtonAction(button, released));
}
trashgod

This LinePanel uses Key Bindings and invokes doClick() in actionPerformed() to achieve an effect similar to the one you describe.

Addendum: As you want the button to appear pressed while the key is pressed, you may be able to use the optional onKeyReleased parameter of KeyStroke.getKeyStroke(). As described in ButtonModel, you'll need to make the model both armed and pressed to simulate a mouse down in the button.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!