Java 动作和动作图-向我解释这种行为

Java 动作和动作图-向我解释这种行为,java,swing,jbutton,key-bindings,abstract-action,Java,Swing,Jbutton,Key Bindings,Abstract Action,我有一个动作 SampleAction a = new SampleAction("foo", null); 然后我将其添加到按钮和动作图中 JButton b = new JButton(a); b.getActionMap().put("bar", a); b.getInputMap().put(KeyStroke.getKeyStroke("F1"), "bar"); 我将跟踪(System.out.println(“Action[“+e.getActionCommand()+”]pe

我有一个
动作

SampleAction a = new SampleAction("foo", null);
然后我将其添加到按钮和动作图中

JButton b = new JButton(a);
b.getActionMap().put("bar", a);
b.getInputMap().put(KeyStroke.getKeyStroke("F1"), "bar");
我将跟踪(
System.out.println(“Action[“+e.getActionCommand()+”]performed!”);
)放在操作中。当我用鼠标按下按钮时,它显示出来了

Action [foo] performed!
但当我使用F1时,它显示:

Action [null] performed!
为什么?



除非我有误解,否则您应该通过
ae.getSource()
ActionEvent
上调用
getActionCommand()
JButton
实例调用
getActionCommand

  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!");
    }
}
更新:

多亏了@Kleopatra,这可能是一种更好的方式:

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!");
        }
    }

除非我有误解,否则您应该通过
ae.getSource()
ActionEvent
上调用
getActionCommand()
JButton
实例调用
getActionCommand

  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!");
    }
}
更新:

多亏了@Kleopatra,这可能是一种更好的方式:

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!");
        }
    }

我无法访问您的
SampleAction
,但我猜您在构造函数中传递的“foo”文本被用作文本,与action命令无关

如果查看
AbstractButton
类,
JButton
从中扩展,您会看到

public String getActionCommand() {
    String ac = getModel().getActionCommand();
    if(ac == null) {
        ac = getText();
    }
    return ac;
}
创建传递给操作的
ActionEvent
时使用此方法。当您单击按钮时,将调用此方法,我假设
ac
null
,但是
getText()
方法返回您在
SampleAction
类中使用的
“foo”


当您通过按F1键直接触发动作时,您将绕过此机制,只需触发该动作。如果您想避免这种情况,可以在
JButton
ActionMap
中添加一个
Action
,它只执行
JButton#doClick
,这是一个API调用,用于在按钮上执行“单击”

我无法访问您的
SampleAction
,但我猜是“foo”在构造函数中传递的文本用作文本,与action命令无关

如果查看
AbstractButton
类,
JButton
从中扩展,您会看到

public String getActionCommand() {
    String ac = getModel().getActionCommand();
    if(ac == null) {
        ac = getText();
    }
    return ac;
}
创建传递给操作的
ActionEvent
时使用此方法。当您单击按钮时,将调用此方法,我假设
ac
null
,但是
getText()
方法返回您在
SampleAction
类中使用的
“foo”


当您通过按F1键直接触发动作时,您将绕过此机制,只需触发该动作。如果你想避免这种情况,你可以在
JButton
ActionMap
中添加一个
Action
,它只做
JButton#doClick
,这是对按钮执行“点击”的API调用

我们可以看到
SimpleAction
类,在那里发布一个@DavidKroukamp吗?为什么问题很难回答(无法观察swing团队开发人员的大脑,即使在现场也看不到,更不用说在过去:-)如果一个动作没有显式设置actionCommmand,它默认为某个动作。这两个位置(AbstractButton.fireActionEvent与SwingUtilities.notifyAction)有所不同actionEvent是在哪里创建的。我们可以看到
SimpleAction
类,在那里发布@DavidKroukamp,你可以看到为什么问题很难回答(不能看到swing团队开发人员的大脑,即使在现场,更不用说在过去:-)如果一个动作没有显式设置actionCommmand,那么它默认为某个动作。在创建actionEvent的两个位置(AbstractButton.fireActionEvent和SwingUtilities.notifyAction)上,该动作是不同的。嗯……这并没有真正回答问题(无论如何,我认为:-)-更多的是当相同的操作用作按钮时(单击时执行),actionCommand的区别vs.用于actionMap。我将
JComponent.当在聚焦窗口中时,它仍在打印
null
,当按F1oh时,现在它是
:P
我只是认为我在键绑定上做错了什么。
:)
但它看起来没问题。问题变了-并且。。。我恐怕还有一个不需要:-)按钮内部默认创建的actionCommand是一个未记录的实现细节(而不是最聪明的事情:名称可能会本地化和更改-不是标识符的好候选)-需要该命令的应用程序代码不能依赖于这样一个windy属性。相反,将其设置为action Plus,它违背了操作的全部目的:它被设计为独立于视图使用(可以是JTextField f.i.或任何其他内容)嗯。。。myAction.putValue(Action.Action\u COMMAND\u KEY,“fooCommand”)有什么问题吗?嗯。。。这并不是真正的回答问题(无论如何,我认为:-)-这更多的是关于当相同的操作被用作按钮时(单击时执行)actionCommand的差异vs.用于actionMap。我将
JComponent.当_在_FOCUSED_窗口中时
,但按F1oh时仍在打印
null
,现在它是
:P
我只是认为我在键绑定方面出了问题<代码>:)
但看起来没问题。问题变形了-而且。。。我恐怕还有一个不需要:-)按钮内部默认创建的actionCommand是一个未记录的实现细节(而不是最聪明的事情:名称可能会本地化和更改-不是标识符的好候选)-需要该命令的应用程序代码不能依赖于这样一个windy属性。相反,将其设置为action Plus,它违背了操作的全部目的:它被设计为独立于视图使用(可以是JTextField f.i.或任何其他)