Java Swing:使用相应的键盘按钮时显示按下的按钮

5
我正在使用Java和Swing制作一个程序,其中包含箭头键的GUI。箭头键对应于键盘上的箭头键。
当我按下键盘上的向上箭头键时,我希望GUI上的向上箭头键显示为被按下。在释放箭头键之前,它应该显示为仍然被按下,并且在释放时也应该释放。
以下是我的代码片段(仅适用于Up按钮),我认为在显示被按下的类别中完全错误:
...
if (e.getKeyCode() == KeyEvent.VK_UP) {
                    actionArrowUp();
                    JButton buttonUp = (JButton) mainTab.getComponent(4);
                    buttonUp.setSelected(true);
                }
...
@Override
public void keyReleased(KeyEvent e) { 
            if (e.getKeyCode() == KeyEvent.VK_UP)
                actionArrowUpRelease();
                buttonUp.setSelected(true);

1
当然,非常抱歉。通常当我收到一个可用的答案时,我会有点匆忙并立刻利用它。对此我深表歉意。 - Sven
2
  1. 或许可以考虑使用键绑定来实现这个功能。
  2. 为了更快地得到帮助,请发布一个SSCCE
  3. 关注其他事项是个好决定。 :)
- Andrew Thompson
2个回答

4

如@trashgod所建议的那样,使用keyBindings是可行的。为了达到在按钮被聚焦时通过空格/回车激活产生的精确的视觉效果,请按以下步骤操作:

  • 实现将委托给按下/释放默认操作的操作
  • 需要同时绑定按键的按下和释放事件以模拟
  • 将绑定安装到按钮父级的输入映射中,类型为WHEN_ANCESTOR

代码如下:

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

+1 代理,避免直接操纵按钮的模型。 - trashgod

4

这个LinePanel使用键绑定并在actionPerformed()中调用doClick()来实现与您描述的类似的效果。

补充说明:如果您希望按钮在按下键时看起来已经被按下,则可以使用KeyStroke.getKeyStroke()的可选参数onKeyReleased。如ButtonModel所述,您需要使模型既武装又按下,以模拟鼠标在按钮上按下。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接