Peut plus d'un ActionListener être court? Puis-je ajouter des arguments à la actionPerformed?

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

  •  22-09-2019
  •  | 
  •  

Question

J'ai une grande table contenant un bouton dans chaque cellule. Ces boutons sont très similaires et font presque le même. Si j'ajouter un écouteur d'action à chaque bouton de cette façon:

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

En fait, chaque auditeur d'action diffère de tous les autres par la valeur de la action. proposition et updatePropositionPanel sont un champ et une méthode de la classe.

  1. Tout d'abord je pensais que je peux le faire plus court si je ne pas utiliser les classes internes. Donc, j'ai décidé de programmer une nouvelle classe ActionListener. Mais que je me suis aperçu que dans ce cas « proposition » ne sera pas visible pour les instances de cette classe.

  2. Alors j'ai décidé d'ajouter la méthode actionPerformed à la classe actuelle et faire: addActionListener(this). Mais que je réalisais que je ne sais pas comment donner des arguments à la méthode actionPerformed.

Alors, comment fonctionne-t-il. Puis-je ajouter un écouteur d'action de manière courte et elegent?

AJOUTEE:

J'ai aimé l'idée de programmer une classe interne avec un constructeur qui peut prendre quelques arguments et méthode actioPerformed, qui peuvent utiliser des arguments donnés dans le constructeur. J'ai commencé à le faire et ensuite rendu compte que cela crée un conflit avec d'autres classes anonymes internes (utilisés comme dans le code ci-dessus). Je pense que je vais créer une autre classe (pas intérieure un).

Était-ce utile?

La solution

Vous pouvez créer votre propre classe et de transmettre les données dans le constructeur. Par exemple

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

Ensuite, vous pouvez l'ajouter comme d'habitude, en passant tous les arguments que vous aimez au constructeur:

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

Autres conseils

EDIT :. Je l'ai modifié la classe pour montrer la construction avec MyOuterClass

Voici un code ébauché. Espérons que cela devient à votre 1, ce qui est de savoir comment je le mettre en œuvre.

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

EDIT :. Pour créer une autre classe que vous avez demandé dans votre édition, faites comme ci-dessus, mais créer une autre catégorie non-privée dans un autre fichier .java et le code de suite

Comme la seule différence est la valeur de action vous pouvez placer le code dans une méthode. (De plus, le @Override est inutile, et += est utile ici.)

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

Le invokeLater est probablement inutile car vous serez sur le fil AWT Dispatch Event (HAE) de toute façon.

Si vous ajoutez beaucoup d'actions à usage général, vous pouvez simplifier en utilisant une interface qui ne dispose pas d'un objet événement inutile associé.

Si vous voulez être hackish vous pouvez ajouter l'auditeur dans un constructeur de sous-classe.

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

Si tout va bien, JDK7 fera la syntaxe Java pour ce genre de chose moins bavard. Java, cependant, toujours un peu bavarde.

Option 1 œuvres si vous faites proposition mutable (par exemple StringBuilder au lieu de String). Option 2 œuvres si vous les déclarer final. De cette façon, ils sont accessibles / visibles dans la classe interne.

Vous pouvez créer une classe MyActionListener séparée et passer la proposition de deux valeurs et de l'action avec le constructeur. Il le code nette sur la source.

Vous pouvez créer votre propre classe auditeur qui implémente ActionListener. Cette classe peut contenir des variables membres correspondant aux paramètres dont vous parlez; vous souhaitez les régler en utilisant le constructeur.

L'appel à ajouter l'auditeur alors ressembler à quelque chose comme ceci:

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

Je suppose que votre proposition et les variables d'action sont des chaînes pour les besoins de cet exemple. Définir une PropositionUpdater d'interface, un PropositionPanelUpdater d'interface, et un support de proposition de collaborateur:

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

La mise en œuvre par défaut d'une proposition de mise à jour est simplement ceci:

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

Je vais laisser la valeur par défaut d'un PropositionHolder et PropositionPanelUpdater à votre imagination;)

Maintenant, voici votre écouteur d'action:

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

Vous n'avez pas dit combien de boutons vous parlez.

Si c'est un petit nombre comme un échiquier ou moins, l'approche @ juskt est un bon.

Cependant, si vous cherchez quelque chose plus, j'utiliser cette approche:

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

Cet écouteur d'action contient pas d'état. Par conséquent, une instance unique de celui-ci peut être utilisé pour tous les boutons. Pour quelque chose comme une carte Go (19x19), cela fonctionne à 1 objet au lieu de 361.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top