Come faccio a livello di programmazione inviare ActionEvent di JButton?

Come faccio a livello di programmazione inviare un ActionEvent (ad esempio premuto il pulsante/ACTION_PERFORMED) per un JButton?

Conosco:

button.doClick(0);

e

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

Ma non è possibile inviare direttamente un ActionEvent?

EDIT: Questo non è il codice di produzione, solo un po ‘ di esperienza personale.

InformationsquelleAutor Anon | 2011-01-20

 

5 Replies
  1. 15

    Si può ottenere un pulsante ActionListeners, e quindi chiamare il actionPerformed direttamente il metodo.

    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);
    }
    • Una cosa da guardare fuori per è che spesso ActionListeners pensare che si sta andando ad essere richiamato sulla EDT, quindi, se avete intenzione di inviarla manualmente dovrai farlo sul EDT così.
    • Per quanto riguarda il mio commento: qualcuno sa di qualche posto dove è documentato che è possibile assumere il ActionListener sarà eseguito sul EDT?
    • È documentato qui: java.sun.com/products/jfc/tsc/articles/threads/… una Volta che la GUI è visibile, la maggior parte dei programmi sono guidati da eventi quali azioni del tasto o click del mouse, che sono sempre trattati nell’evento-spedizione thread Da lì si può supporre che corrono in EDT.
  2. 13

    Anche se è impossibile, perché si vuole? Di solito quando la gente vuole fare qualcosa di simile a questo, vuol dire che non hai correttamente separate le preoccupazioni dell’interfaccia utente dalla logica di business. In genere si desidera richiamare un po ‘ di logica che si verifica in un ActionListener senza che l’azione abbia luogo.

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

    Ma in realtà la soluzione è di estrarre la logica di ActionListener e invocare da entrambe le ActionListener e che secondo percorso:

    public void someLogic() {
        //SomeLogic
    }
    
    public void actionPerformed(ActionEvent ae) {
        someLogic();
    }
    
    //...
    
    public void someOtherPlace() {
        someLogic();
    }
    • Mentre questo è un buon commento, davvero non rispondere alla domanda.
    • così si downvote buon consiglio, anche se aiuta la OP di più di un straight-up “risposta”? Non è molto utile.
    • Beh, sì, ma ho una buona ragione per questo. La tua risposta non è davvero una risposta, un commento ( molto buono ) , e c’è un posto per i commenti sotto a destra, la domanda originale. Questo non è personale, naturalmente.
    • Beh, è stato destinato ad essere una risposta che c’è una buona probabilità che non risolve del po problema (e se non l’OP che quasi certamente qualcuno arriva più tardi), se non le loro specifiche domanda. Ma trovo che è necessario per consentire eccezioni, anche quando dovrebbe essere un commento. Non avrei potuto fare questa spiegazione in un altro commento, a causa di limiti tecnici.
    • ebbene si può ( non mi sorprende tu non lo sai, perché sei sicuramente non un newbie ) Che la comunità wiki, sono per. Ma di nuovo, io avevo intenzione di prendere questo personale. Così, è possibile “toccare” la tua risposta, così posso portare il mio downvote indietro? Avrai il tuo +2 pts. indietro e vado a prendere il mio +1 pt. i.imgur.com/CAgjP.png
    • Lol io odio che il voto di chiusura. Certo che io ti tocco, anche se non era così preoccupato per la d/v quanto realmente interessati al tuo POV. Io ho visto abbastanza per sapere che non è personale. Come per la CW, non credo che serva a tutti. Persone abuso da usarlo come un modo per non ottenere rep per una risposta; è fatto per la collaborazione risposte/domande. Si sta solo dicendo che non dovrei ottenere rep per questa risposta che mi sostengono contro perche ‘penso che questa in particolare è una vera e propria risposta :-).
    • “Perché?” Beh, voglio perché sto scrivendo un test automatizzato, e voglio UI copertura troppo… sto facendo di sbagliato? Edit: Oh, NVM-ho solo bisogno di doClick. OK, ho capito.

  3. 3

    Solo se si eredita, e di esporre il fireActionPerformed metodo, che è protetto:

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

    Allora si sarà in grado, ma, naturalmente, è necessario utilizzare un riferimento di come questo:

    MockButton b = .... 
    
    b.fireActionPerformed( new Action... etc. etc

    Perché vorreste fare? Non so, ma io vi consiglio di seguire Marco, consigli

  4. 1

    Se non si desidera chiamare doClick() sul pulsante, quindi si può semplicemente chiamare il codice chiamato dall’azione del pulsante. Forse si vuole avere qualunque sia la classe che contiene il metodo actionPerformed chiamare un metodo pubblico che le altre classi possono chiamare, e semplicemente chiamare questo metodo.

  5. 0

    Pratica il problema è stato risolto, sembra (vedere Mark Peters’ e jjnguy s risposte). E il fireActionPerformed metodo è stato anche già detto (vedi OscarRyz’ la risposta), per evitare potenziali problemi di concorrenza.

    Quello che volevo aggiungere è che si può chiamare tutti i privati e i metodi protetti (tra cui fireActionPerformed), senza la necessità di creare una sottoclasse a tutte le classi, utilizzando la reflection. Primo, si ottiene la riflessione Method oggetto di un metodo privato o protetto con method = clazz.getDeclaredMethod() (clazz deve essere il Class oggetto di th che dichiara il metodo, non una delle sue sottoclassi (cioè AbstractButton.class per il metodo fireActionPerformed, non JButton.class)). Quindi, chiamare method.setAccessible(true) per sopprimere il IllegalAccessExceptions che altrimenti verificarsi quando si tenta di accedere private o protected, metodi e campi. Infine, chiamare method.invoke().

    Io non ne so abbastanza su di riflessione, tuttavia, per essere in grado di elencare gli svantaggi dell’utilizzo di riflessione. Esistono, però, secondo il Riflessione API trail (vedere la sezione “Inconvenienti di Riflessione”).

    Ecco qualche codice di lavoro:

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

Lascia un commento