Как программно отправить ActionEvent в JButton?

как программно отправить ActionEvent (например, кнопка нажата/ACTION_PERFORMED) до JButton?

Я знаю:

button.doClick(0);

и

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

но разве нельзя напрямую отправить его ActionEvent?

EDIT: это не производственный код, это просто небольшой личный эксперимент.

5 ответов


вы можете получить кнопки 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);
}

даже если бы вы могли, почему вы хотите? Обычно, когда люди хотят сделать что-то подобное, это означает, что они не правильно разделил озабоченность пользовательского интерфейса от бизнес-логики. Обычно они хотят вызвать некоторую логику, которая происходит в 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();
}

только если вы наследуете и разоблачить 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

почему вы хотите это сделать? Я не знаю, но я бы посоветовал вам следовать Марка!--4-->


Если вы не хотите вызывать doClick() на кнопке, то вы можете просто вызвать код, вызванный действием кнопки. Возможно, вы хотите, чтобы любой класс, содержащий метод actionPerformed, вызывал открытый метод, который могут вызывать другие классы, и просто вызывал этот метод.


практическая проблема была решена, кажется (см. Марк Питерс' и jjnguy это ответы). И fireActionPerformed метод также уже упоминался (см. OscarRyz' ответ), для избежания потенциальных проблем параллелизма.

Я хотел добавить, что ты can вызовите все частные и защищенные методы (включая fireActionPerformed), без необходимости подкласса каких-либо классов, используя отражение. Во-первых, вы получаете отражение Method объект частного или защищенного метода с method = clazz.getDeclaredMethod() (clazz должен быть Class объект th класса, который объявляет метод, а не один из его подклассов (т. е. AbstractButton.class для метода fireActionPerformed, не JButton.class)). Тогда вы звоните method.setAccessible(true) для подавления IllegalAccessExceptions, которые в противном случае возникнут при попытке доступа к частным или защищенным методам/полям. Наконец, вы звоните method.invoke().

Я не знаю достаточно об отражении, однако, чтобы иметь возможность перечислить недостатки использования отражения. Однако они существуют, согласно отражение 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);
    }
}