将多个键绑定附加到 java swing 对象

Attaching multiple keybindings to a java swing object

我在尝试使用键盘控件使 "player" 图标在我的 JFrame 周围移动时遇到问题。我有一个对象,我想使用 w、a、s 和 d 键四处移动。我正在使用键绑定,因为在我的研究中它们似乎更适合这项任务。

我已经设法将所有需要的键附加到我的图标上,它们都调用了动作,唯一的问题是我无法区分按下的是哪个按钮。我希望这可以通过在我的动作事件中使用 getActionCommand() 以某种方式完成。目前还没有成功。

我看到的其他示例似乎对此有解决方案,但它们也有很多额外的代码,注释很少,因此很难确定实际发生了什么。它们似乎都涉及多个 类,方法和字段。我希望减少这段代码的参与度。

我想知道的是:实现此功能的最佳方法是什么?我可以用键绑定来做吗?真的需要很复杂吗?

我非常感谢任何帮助,即使它只是我可以用来帮助自己找到答案的资源。

这是我现有的代码:

//My method that gets called by the constructor
//This is all based on a tutorial I found: ftp://ecs.csus.edu/clevengr/133/handouts/UsingJavaKeyBindings.pdf
//player is just an image icon
public static void setUpKeys() {
    InputMap playerMap = player.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

    KeyStroke wKey = KeyStroke.getKeyStroke('w');
    KeyStroke aKey = KeyStroke.getKeyStroke('a');
    KeyStroke sKey = KeyStroke.getKeyStroke('s');
    KeyStroke dKey = KeyStroke.getKeyStroke('d');
    KeyStroke wSprint = KeyStroke.getKeyStroke((char) ('w' + KeyEvent.SHIFT_DOWN_MASK)); //As a side note, what's the best way to get it to move faster when the shift key is held down? Not that important, but if someone happens to know, that'd be great

    playerMap.put(wKey, "moveUp");
    playerMap.put(aKey, "moveLeft");
    playerMap.put(sKey, "moveDown");
    playerMap.put(dKey, "moveRight");
    playerMap.put(wSprint, "moveFast");

    ActionMap playerAction = player.getActionMap();

    playerAction.put("moveUp", playerMoved);
    playerAction.put("moveLeft", playerMoved);
    playerAction.put("moveDown", playerMoved);
    playerAction.put("moveRight", playerMoved);
    playerAction.put("moveFast", playerMoved);
}

这是我的 playerMoved 动作:

static Action playerMoved = new AbstractAction() {
    //This isn't important, just put it in instead of suppressing the warning
    private static final long serialVersionUID = 2L; 

    //This doesn't do anything yet, just gives console confirmation
    public void actionPerformed(ActionEvent e) {
        System.out.println("Activated");

        //Here's what I was talking about with the getActionCommand() not working
        if (e.getActionCommand().equals("moveUp")) {
            System.out.println("up");
        }
    }
};

如果有人需要我的代码的任何其他部分,我可以提供。我只是想将其简化为我认为对这个问题很重要的内容

I was hoping this could be accomplished in some way by using the getActionCommand() on my action event.

您不想这样做,因为您会尝试将 "action command" 用于 "processing"。这不是一个好的设计,因为它会导致嵌套的 if/else 语句。

相反,您需要创建一个 Action 接受参数来控制移动。所以你需要 4 个独立的 Actions 来控制运动。有关此方法的完整工作示例,请参阅 Motion Using the Keyboard 中的 MotionWithKeyBindings 示例。

它演示了如何通过为 Action 指定参数使简单的 Action 可重用。这比您当前的操作提供了更大的灵活性。

注1:

您在 Action 中使用以下调试代码:

System.out.println("Activated");

与其简单地显示硬编码值,还不如做类似

的事情
System.out.println( e.getActionCommand() );

在这种情况下,您应该注意到值是 "a, s, w, d",这是您用来调用 Action.

KeyStroke

所以这意味着 if 语句应该测试上述任一字符,而不是字符串 "moveUp",它是用于识别 ActionMap 中的 Action 的字符串.

但是,如上所述,这不是您应该使用的解决方案,我只是想更好地解释 "action command" 是如何确定的。

注二:

您唯一可能想要使用单个 ActiongetActionCommand() 方法的情况是当您想要将 "action command" 用作 "data" 时 Action

有关此方法的示例,请查看:。这是一个简单的数字输入面板的示例,其中按下的数字键被添加到文本字段。因此,关键字符成为文本字段的数据,不需要特殊处理。