0

I need to bind all the arrow keys to perform the same function but each time get which key was pressed. Currently I only have when the right arrow key is pressed via the following

DoneImg.getInputMap(JLabel.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "UpArrow");

Action MvRight = new AbstractAction()
{
     public void actionPerformed(ActionEvent e)
     {
           //Do whatever here
     }
};
DoneImg.getActionMap().put("RightArrow", MvRight);

But I need something like

DoneImg.getInputMap(JLabel.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "RightArrow");
     DoneImg.getInputMap(JLabel.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "LeftArrow");
     DoneImg.getInputMap(JLabel.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "DownArrow");
     DoneImg.getInputMap(JLabel.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "UpArrow");

     Action MvAll = new AbstractAction()
         {
                 public void actionPerformed(ActionEvent e)
              {
                  if (e.keypressed == "LeftArrow")
                         {System.out.println("The left arrow was pressed!");}
                  if (e.keypressed == "RightArrow")
                         {System.out.println("The right arrow was pressed!");}
                  //and so forth
              }
                 };
     DoneImg.getActionMap().put("RightArrow", MvAll);
     DoneImg.getActionMap().put("LeftArrow", MvAll);
     DoneImg.getActionMap().put("UpArrow", MvAll);
     DoneImg.getActionMap().put("DownArrow", MvAll);
syb0rg
  • 8,057
  • 9
  • 41
  • 81
RADXack
  • 1,032
  • 3
  • 11
  • 17

2 Answers2

11

What you're asking is actually counter intuitive and goes against the design of the key bindings API.

The intention is to provide a single unit of work per key stroke. That would, in my mind, suggest that you should have separate action for each arrow key.

It makes it much easier to follow the logic, make changes, circumvent the actions as you need.

But who am I to say what's right :P

If you can't see you way around it, one way would simple be to assign a "command" to each action that you could then interrogate when the actionPerformed is fired.

public TestKeyBindings02() {
    JPanel panel = new JPanel();
    InputMap im = panel.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
    ActionMap am = panel.getActionMap();

    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "RightArrow");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "LeftArrow");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "UpArrow");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "DownArrow");

    am.put("RightArrow", new ArrowAction("RightArrow"));
    am.put("LeftArrow", new ArrowAction("LeftArrow"));
    am.put("UpArrow", new ArrowAction("UpArrow"));
    am.put("DownArrow", new ArrowAction("DownArrow"));
}

public class ArrowAction extends AbstractAction {

    private String cmd;

    public ArrowAction(String cmd) {
        this.cmd = cmd;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (cmd.equalsIgnoreCase("LeftArrow")) {
            System.out.println("The left arrow was pressed!");
        } else if (cmd.equalsIgnoreCase("RightArrow")) {
            System.out.println("The right arrow was pressed!");
        } else if (cmd.equalsIgnoreCase("UpArrow")) {
            System.out.println("The up arrow was pressed!");
        } else if (cmd.equalsIgnoreCase("DownArrow")) {
            System.out.println("The down arrow was pressed!");
        }
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • A question on this: I'm creating a game using a JFrame with a JPanel inside it. Should I still have the keys bound to the panel? or should i somehow put it on the frame? – Goatcat Jul 23 '13 at 08:22
  • Personally, you should use the top container of your game. You should avoid extending from top level containers, like `JFrame`, and instead container your application to something like `JPanel`, this way you can better control how the application is deployed. – MadProgrammer Jul 23 '13 at 10:57
  • Thanks, MP. That made my life so much simpler when trying to solve the confusion of KeyEvents used as ActionEvents for arrow keys. – Falsoon Jul 31 '20 at 18:12
2

You don't have access to the KeyStroke that caused the Action to be executed. So you need to create 4 Actions and pass in a parameter to the Action. Something like:

class SomeAction extends AbstractAction
{
    public SomeAction(String name)
    {
        putValue(Action.NAME, name);
        putValue(ACTION_COMMAND_KEY, "Command: " + name);
    }

    public void actionPerformed(ActionEvent e)
    {
        System.out.println("Name: " + getValue(Action.NAME) );
        System.out.println(e.getActionCommand());
    }
}

You add the Actions to the ActionMap like:

DoneImg.getActionMap().put("RightArrow", new SomeAction("RightArrow"));
DoneImg.getActionMap().put("LeftArrow", new SomeAction("LeftArrow"));
DoneImg.getActionMap().put("UpArrow", new SomeAction("UpArrow"));
DoneImg.getActionMap().put("DownArrow", new SomeAction("DownArrow"));

So you share the same basic functionality,but just identify each Action with an identifier.

camickr
  • 321,443
  • 19
  • 166
  • 288