Può aggiunta di un ActionListener essere breve? Posso aggiungere argomenti al actionPerformed?

StackOverflow https://stackoverflow.com/questions/2515552

  •  22-09-2019
  •  | 
  •  

Domanda

Ho un grande tavolo che contiene un pulsante in ogni cella. Questi pulsanti sono molto simili e fanno quasi la stessa. Se aggiungo un listener di azione per ogni tasto in questo modo:

tmp.addActionListener(new ActionListener(){
   @Override
   public void actionPerformed(ActionEvent evt) {
      proposition = proposition + action;
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            updatePropositionPanel();
         }
      });
   }
});

In realtà, ogni ascoltatore azione differisce da tutti gli altri dal valore della action. proposition e updatePropositionPanel sono un campo e un metodo della classe.

  1. Per prima cosa ho pensato che posso renderlo più breve, se io non uso classi interne. Così, ho deciso di programmare una nuova classe ActionListener. Ma quanto mi sono reso conto che in questo caso "proposizione" non sarà visibile alle istanze di questa classe.

  2. Poi ho deciso di aggiungere il metodo actionPerformed alla classe corrente e farlo: addActionListener(this). Ma quanto mi sono reso conto che io non so come dare argomenti del metodo actionPerformed.

Quindi, come funziona. Posso aggiungere un listener di azione in un modo breve e elegent?

ha aggiunto:

Mi piaceva l'idea di programmare una classe interna con un costruttore che può richiedere alcuni argomenti e modalità actioPerformed, che possono utilizzare argomenti forniti nel costruttore. Ho iniziato a farlo e poi capito che crea un conflitto con altre classi anonime interne (utilizzati come nel dato codice di cui sopra). Quindi, penso che creare un'altra classe (non più interno).

È stato utile?

Soluzione

È possibile creare la propria classe e passare i dati al costruttore. Ad esempio

public class MyActionListener
{
    private int proposition;
    private MyOtherClass moc;

    public MyActionListener(int proposition, MyOtherClass moc) {
        this.proposition = proposition;
        this.moc = moc;
    }

    public void actionPerformed(ActionEvent evt) {
        proposition += moc.action;
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                moc.updatePropositionPanel();
            }
        });
    }
}

Quindi è possibile aggiungerlo come normale, passando qualsiasi argomento che ti piace al costruttore:

tmp.addActionListener( new MyActionListener(proposition, this) );

Altri suggerimenti

Modifica :. Ho cambiato la classe per mostrare costruzione con MyOuterClass

Ecco il codice delineato. Speriamo che questo ottiene al vostro 1, che è come avrei attuarla.

public class MyOuterClass {
    // member variables for MyOuterClass

    public MyOuterClass() {
        // ...constructor stuff here
    }
    // ...outer class stuff here - methods, etc.

    // The code each place you want to add the listener, somewhere in MyOuterClass
    tmp.addActionListener(new MyActionListener(poposition, action));


    // below outer class stuff, although it can really be most places, I usually put
    // it here - personal style preference.  Swing's classes often put inner
    // classes first

    /**
     * An inner class.
     */
    private MyActionListener implements ActionListener {
        /**
      * Object used here as a filler, replace with appropriate
      * class types
      */
        private Object proposition;
        private Object action;

        private MyActionListener(Object proposition, Object action) {
            this.proposition = proposition;
            this.action = action;
        }
        public void actionPerformed(ActionEvent evt) {
          proposition = proposition + action;
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                updatePropositionPanel();
             }
        }
        /**
         * Setters provided in case you need to change proposition and action.  If not,
         * feel free not to have them and to have final members
         */
        private void setProposition(Object proposition) {
            this.proposition = proposition;
        }
        private void setAction(Object action) {
            this.action = action;
        }
    }
}

Modifica :. Per creare un altro classe come lei ha chiesto a tua modifica, fare come sopra, ma di creare un altra classe non privato in un altro file .java e il codice via

Come l'unica diversa è nel valore della action è possibile inserire il codice all'interno di un metodo. (Anche la @Override non è necessaria, e += è utile qui.)

public void setup(
    final AbstractButton button,
    final int action
) { 
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            proposition += action;
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                   updatePropositionPanel();
                }
           });
        }
    });
}

Il invokeLater è probabilmente inutile come si sarà sul filo AWT Event Dispatch (EDT) in ogni caso.

Se si aggiunge un sacco di azioni di uso generale, allora si potrebbe semplificare utilizzando un'interfaccia che non dispone di un oggetto evento inutile ad esso associati.

Se si voleva essere hacker si potrebbe aggiungere l'ascoltatore in un costruttore sottoclasse.

    new ActionHandler(button) { public void action() {
        proposition += action;
        updatePropositionPanel();
    }});

Si spera, JDK7 renderà la sintassi di Java per questo genere di cose meno prolissa. Java, tuttavia, essere sempre un po 'prolisso.

Opzione 1 opere se fate proposition mutabile (per esempio StringBuilder invece di String). Opzione 2 opere se si dichiara loro final. In questo modo sono accessibili / visibili nella classe interna.

Si potrebbe creare una classe MyActionListener separata e passare la proposta due valori e di azione con il costruttore. E declutters il codice sorgente.

È possibile creare la propria classe ascoltatore che implementa ActionListener. Questa classe potrebbe contenere variabili membro corrispondenti ai parametri si sta parlando; quando si imposta utilizzando il costruttore.

La chiamata di aggiungere l'ascoltatore sarebbe quindi simile a questa:

tmp.addActionListener(new MyActionListenerSubClass(proposition, action));

darò per scontato che le variabili di proposta e di azione sono le stringhe per il bene di questo esempio. Definire un PropositionUpdater di interfaccia, un PropositionPanelUpdater interfaccia, e un supporto collaboratrice proposizione:

public interface PropositionUpdater() {
    public void updateProposition(PropositionHolder holder, String action);
}

public interface PropositionHolder() {
    public String getProposition();

    public void setProposition(String proposition);
}

public interface PropositionPanelUpdater() {
    public void updatePropositionPanel();
}

L'implementazione predefinita di un programma di aggiornamento proposizione è semplicemente questo:

public class DefaultPropositionUpdater implements PropositionUpdater {
    public void updateProposition(final PropositionHolder holder, final String action) {
        holder.setProposition(holder.getProposition() + action);
    }
}

Ti lascio il default di un PropositionHolder e PropositionPanelUpdater alla vostra immaginazione;)

Ora, ecco la vostra action listener:

public class PropositionUpdaterActionListener implements ActionListener {
    private PropositionHolder holder;

    private PropositionUpdater updater;

    private PropositionPanelUpdater panelUpdater;

    public PropositionUpdaterActionListener(final PropositionHolder holder, final PropositionUpdater updater, final PropositionPanelUpdater panelUpdater) {
        super();
        this.holder = holder;
        this.updater = updater;
        this.panelUpdater = panelUpdater;
    }

    public void actionPerformed(final ActionEvent evt) {
        //Not sure how you *got* the action, but whatever...
        updater.updateProposition(holder, action);
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                panelUpdater.updatePropositionPanel();
            }
        });
    }
}

Non hai detto quanti pulsanti si sta parlando.

Se si tratta di un piccolo numero, come una scacchiera o meno, l'approccio di @ juskt è un buon compromesso.

Tuttavia, se si guarda a qualcosa di più grande, vorrei utilizzare questo metodo:

public class MyActionListener {
      public void actionPerformed(ActionEvent evt) {
          JComponent c = (JComponent)evt.getSoource();
          int prop = (Integer)c.getclientProperty("PROPOSITION");
          int act = (Integer)c.getclientProperty("ACTION");
          SomeClass obj = c.getclientProperty("UPDATE");
          prop += act;
          // If necessary, clientPut("PROPOSITION", prop);
          SwingUtilities.invokeLater(new    Runnable() {
              public void run() {
                  obj.updatePropositionPanel();
              }
          });
      }
}

Questa action listener tiene nessuno stato. Come risultato, una singola istanza di esso può essere utilizzato per tutti i pulsanti. Per qualcosa di simile a una scheda di Go (19x19), questo funziona a 1 oggetto invece di 361.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top