15

如何以编程方式将ActionEvent(例如按下按钮/ACTION_PERFORMED)发送到JButton

我知道:

button.doClick(0);

button.getModel().setArmed(true);
button.getModel().setPressed(true);
button.getModel().setPressed(false);
button.getModel().setArmed(false);

但是不能直接发送ActionEvent吗?

编辑:这不是生产代码,它只是一个小小的个人实验。

4

5 回答 5

17

可以获取一个按钮的ActionListeners,然后actionPerformed直接调用该方法。

ActionEvent event;
long when;

when  = System.currentTimeMillis();
event = new ActionEvent(button, ActionEvent.ACTION_PERFORMED, "Anything", when, 0);

for (ActionListener listener : button.getActionListeners()) {
    listener.actionPerformed(event);
}
于 2011-01-20T21:54:37.290 回答
14

就算可以,又何必呢?通常当人们想做这样的事情时,这意味着他们没有正确地将 UI的关注点与业务逻辑分开。通常,他们希望调用发生在 ActionListener 中的一些逻辑,而无需执行操作。

public void actionPerformed(ActionEvent ae) {
    //SomeLogic
}

//...

public void someOtherPlace() {
    //I want to invoke SomeLogic from here though!
}

但真正的解决方案是从 ActionListener 中提取该逻辑并从 ActionListener 和第二个位置调用它:

public void someLogic() {
    //SomeLogic
}

public void actionPerformed(ActionEvent ae) {
    someLogic();
}

//...

public void someOtherPlace() {
    someLogic();
}
于 2011-01-20T21:54:07.443 回答
3

仅当您继承并公开受保护的fireActionPerformed方法时:

class MockButton extends JButton { 
   // bunch of constructors here 
   @Override 
   public void fireActionPerformed( ActionEvent e ) { 
       super.fireActionPerformed( e );
   }
}

然后你就可以了,但当然,你必须使用这样的参考:

MockButton b = .... 

b.fireActionPerformed( new Action... etc. etc

你为什么要这样做?我不知道,但我建议你听从马克的建议

于 2011-01-20T21:55:17.520 回答
1

如果您不想在按钮上调用 doClick(),那么您可以简单地调用按钮操作调用的代码。也许您希望拥有 actionPerformed 方法的任何类调用其他类可以调用的公共方法,并简单地调用此方法。

于 2011-01-20T21:55:09.250 回答
0

实际问题似乎已解决(参见Mark Petersjjnguy 的答案)。并且该fireActionPerformed方法也已经被提及(参见OscarRyz 的回答),用于避免潜在的并发问题。

我想补充的是,您可以调用所有私有和受保护的方法(包括fireActionPerformed),而无需使用反射对任何类进行子类化。首先,你得到Method一个私有或受保护方法的反射对象method = clazz.getDeclaredMethod()clazz需要是Class声明该方法的类的对象,而不是它的子类之一(即AbstractButton.class对于方法fireActionPerformed不是 JButton.class))。然后,您调用method.setAccessible(true)以抑制IllegalAccessException在尝试访问私有或受保护的方法/字段时会出现的 s。最后,您调用method.invoke().

然而,我对反射的了解还不够,无法列出使用反射的缺点。但是,根据反射 API 跟踪,它们存在(参见“反射的缺点”部分)。

这里有一些工作代码:

// ButtonFireAction.java
import javax.swing.AbstractButton;
import javax.swing.JButton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Method;

public class ButtonFireAction
{
    public static void main(String[] args) throws ReflectiveOperationException
    {
      JButton button = new JButton("action command");
      Class<AbstractButton> abstractClass = AbstractButton.class;
      Method fireMethod;

      // signature: public ActionEvent(Object source, int id, String command)
      ActionEvent myActionEvent = new ActionEvent(button,
                                                  ActionEvent.ACTION_PERFORMED,
                                                  button.getActionCommand());
      button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e)
        {
          System.out.println(e.getActionCommand());
        }
      });

      // get the Method object of protected method fireActionPerformed
      fireMethod = abstractClass.getDeclaredMethod("fireActionPerformed",
                                                   ActionEvent.class);
      // set accessible, so that no IllegalAccessException is thrown when
      // calling invoke()
      fireMethod.setAccessible(true);

      // signature: invoke(Object obj, Object... args)
      fireMethod.invoke(button,myActionEvent);
    }
}
于 2014-05-23T20:36:02.660 回答