Fabricio
Fabricio

Reputation: 7925

Action and ActionMap - Explain me this behavior

I have an Action

SampleAction a = new SampleAction("foo", null);

Then I add it to a Button, and to an ActionMap

JButton b = new JButton(a);
b.getActionMap().put("bar", a);
b.getInputMap().put(KeyStroke.getKeyStroke("F1"), "bar");

I put a trace (System.out.println("Action [" + e.getActionCommand() + "] performed!");) inside the Action. When I press the button with mouse it shows

Action [foo] performed!

But when i use F1, it shows:

Action [null] performed!

Why?


class SampleAction extends AbstractAction
{
    public SampleAction(String text, Icon icon) {
        super(text, icon);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Action [" + e.getActionCommand() + "] performed!");
    }
}

Upvotes: 3

Views: 2371

Answers (2)

David Kroukamp
David Kroukamp

Reputation: 36423

Unless I am misunderstanding You should call getActionCommand on the instance of your JButton via ae.getSource() where as you are calling getActionCommand() on the ActionEvent:

  SampleAction a = new SampleAction("foo", null);

  JButton b = new JButton(a);
  b.getActionMap().put("bar", a);
  b.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F1"), "bar");

class SampleAction extends AbstractAction
{
    public SampleAction(String text, Icon icon) {
    super(text, icon);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
    System.out.println("Action [" + ((JButton)e.getSource()).getActionCommand() + "] performed!");
    }
}

UPDATE:

Thanks to @Kleopatra this might be a better way:

SampleAction a = new SampleAction("foo", null);

JButton b = new JButton(a);
b.getActionMap().put("bar", a);
b.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F1"), "bar");

 class SampleAction extends AbstractAction {

        public SampleAction(String text, Icon icon) {
            super(text, icon);

            putValue(Action.ACTION_COMMAND_KEY, text);//'foo' will be printed when button clicekd/F1 pressed
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Action [" + e.getActionCommand() + "] performed!");
        }
    }

Upvotes: 3

Robin
Robin

Reputation: 36601

I have no access to your SampleAction, but I guess the "foo" text you pass in the constructor is used as a text and has nothing to do with the action command.

If you look into the AbstractButton class from which JButton extends, you see

public String getActionCommand() {
    String ac = getModel().getActionCommand();
    if(ac == null) {
        ac = getText();
    }
    return ac;
}

This method is used when creating the ActionEvent which is passed to the action. When you click the button, this method is called and I assume ac is null but the getText() method returns the "foo" you used in your SampleAction class.

When you trigger the action directly by pressing F1, you bypass this mechanism and simply trigger the action. If you want to avoid this, you can add an Action to the ActionMap of the JButton which simply does JButton#doClick, which is the API call to perform a "click" on the button

Upvotes: 1

Related Questions