如何以编程方式将ActionEvent发送到JButton?

时间:2011-01-20 21:47:50

标签: java swing event-handling jbutton actionlistener

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

我知道:

button.doClick(0);

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

但是不能直接发送ActionEvent吗?

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

5 个答案:

答案 0 :(得分:15)

您可以获得按钮ActionListener,然后直接调用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);
}

答案 1 :(得分:13)

即使你可以,你为什么要这样做?通常当人们想要做这样的事情时,这意味着他们没有正确将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();
}

答案 2 :(得分: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

你为什么要这样做?我不知道,但我建议您关注Mark's advice

答案 3 :(得分:1)

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

答案 4 :(得分:0)

看来实际问题已经解决了(见Mark Peters'jjnguy's答案)。并且还提到了fireActionPerformed方法(请参阅OscarRyz' answer),以避免潜在的并发问题。

我想要添加的是可以调用所有私有和受保护的方法(包括fireActionPerformed),而无需使用反射对任何类进行子类化。首先,使用Method获取私有或受保护方法的反射method = clazz.getDeclaredMethod()对象(clazz需要是声明方法的类的Class对象,而不是其子类(即AbstractButton.class用于方法fireActionPerformed不是 JButton.class))。然后,您调用method.setAccessible(true)来禁止在尝试访问私有或受保护的方法/字段时会发生的IllegalAccessException。最后,请致电method.invoke()

然而,我对反射知之甚少,能够列出使用反射的缺点。但是,根据Reflection API trail,它们存在(参见“反思的缺点”)。

这里有一些工作代码:

// 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);
    }
}