Puede adición de un ActionListener ser corto? ¿Puedo añadir argumentos a la actionPerformed?

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

  •  22-09-2019
  •  | 
  •  

Pregunta

Tengo una tabla grande que contiene un botón en cada celda. Estos botones son muy similares y hacen casi lo mismo. Si añado un oyente de action a todos los botones de esta manera:

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

En realidad, cada oyente acción se diferencian de todos los demás por el valor de la action. proposition y updatePropositionPanel son un campo y un método de la clase.

  1. Primero pensé que puedo hacerlo más corto si yo no uso clases internas. Por lo tanto, decidí programar una nueva clase ActionListener. Pero lo que me di cuenta de que en este caso "proposición" no serán visibles a las instancias de esta clase.

  2. A continuación, he decidido añadir el método actionPerformed a la clase actual y hacer que: addActionListener(this). Pero lo que me di cuenta de que no saben cómo dar a los argumentos del método actionPerformed.

Así que, ¿cómo funciona. ¿Puedo añadir un detector de acción de una manera corta y elegent?

AÑADIDO:

Me gustaba la idea de programar una clase interna con un constructor que puede tomar algunos argumentos y método actioPerformed, que pueden usar argumentos dados en el constructor. Empecé a hacerlo y entonces se dio cuenta de que crea un conflicto con otras clases anónimas internas (utilizados al igual que en el código anterior dado). Por lo tanto, creo que voy a crear otra clase (no interior).

¿Fue útil?

Solución

Usted puede crear su propia clase y pasar los datos al constructor. Por ejemplo

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

A continuación, se puede añadir como algo normal, que pasa a lo le argumentos como al constructor:

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

Otros consejos

Editar . He alterado la clase a la feria de la construcción con MyOuterClass

Aquí hay un código esbozado. Con suerte esto se pone a su 1, que es lo que iba a ponerlo en práctica.

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

Editar . Para crear otra clase que usted solicitó en su edición, hacer que el anterior pero crear una otra clase no privado al otro archivo .java y el código de distancia

Como el único diferente es en el valor de action se puede colocar el código dentro de un método. (También el @ Override es innecesaria, y += es útil aquí.)

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

El invokeLater es probablemente inútil ya que estará en el hilo AWT Evento de Despacho (EDT) de todos modos.

Si va a añadir un montón de acciones de propósito general, entonces se podría simplificar mediante el uso de una interfaz que no tiene sentido un objeto de evento asociado a él.

Si usted quería ser hacker podría añadir al oyente en un constructor de la subclase.

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

Con suerte, JDK7 hará que la sintaxis de Java para este tipo de cosas menos detallado. Java, sin embargo, siempre será un tanto prolijo.

Opción 1 funciona si usted hace mutable proposition (por ejemplo, en lugar de StringBuilder String). Opción 2 funciona si los declaran final. Esta forma en que están accesibles / visible en la clase interna.

Se podría crear una clase separada MyActionListener y aprobar la proposición y la acción dos valores con el constructor. Se elimina los líos del código fuente.

Se puede crear su propia clase de escucha que implementa ActionListener. Esta clase puede contener variables de miembros correspondientes a los parámetros que estamos hablando; lo haces con ellas mediante el constructor.

La llamada a añadir al oyente a continuación, sería algo como esto:

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

Vamos a suponer que las variables de proposición y de acción son Cuerdas para el bien de este ejemplo. Definir una PropositionUpdater interfaz, un PropositionPanelUpdater interfaz, y un soporte de proposición colaborador:

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 implementación predeterminada de un actualizador proposición es simplemente esto:

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

voy a dejar el valor por defecto de un PropositionHolder y PropositionPanelUpdater a su imaginación;)

Ahora, aquí está el oyente de 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();
            }
        });
    }
}

no dijo cuántos botones que está hablando.

Si se trata de un número pequeño como un tablero de ajedrez o menos, el enfoque de @ juskt es una buena.

Sin embargo, si se mira algo más grande, me gustaría utilizar este enfoque:

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

Esta acción oyente tiene ningún estado. Como resultado, una sola instancia de que puede ser utilizado para todos los botones. Para algo así como un tablero de Go (19x19), esto funciona a 1 objeto en lugar de 361.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top