2009-05-21 16 views
5

Hace poco estaba haciendo una asignación de programación que nos requería implementar en código un programa especificado por un diagrama UML. En un punto, el diagrama especificó que tenía que crear un JButton anónimo que mostrara un recuento (comenzando en uno) y decrementara cada vez que se hacía clic. El JButton y su ActionListener tenían que ser anónimos.clase anónima de Java que implementa ActionListener?

me ocurrió con la siguiente solución:

public static void main(String[] args) { 
    JFrame f = new JFrame("frame"); 
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    f.setSize(400, 400); 

    f.getContentPane().add(new JButton() { 

    public int counter; 

    { 
     this.counter = 1; 
     this.setBackground(Color.ORANGE); 
     this.setText(this.counter + ""); 

     this.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent arg0) { 
      counter --; 
      setText(counter + ""); 
     } 
     }); 

    } 
    }); 

    f.setVisible(true); 

}

Esto añade un JButton en el anonimato, a continuación, añade otro ActionListener anónima (interno) para controlar los eventos y actualizar el texto del botón según sea necesario. ¿Hay una mejor solución? Estoy bastante seguro de que no puedo declarar un JButton implements ActionListener() anónimo, pero ¿hay alguna otra forma más elegante de lograr el mismo resultado?

+0

Mira dónde estás ahora @Tim – Insane

Respuesta

11

por lo general más o menos así:

JPanel panel = new JPanel(); 
panel.add(new JButton(new AbstractAction("name of button") { 
    public void actionPerformed(ActionEvent e) { 
     //do stuff here 
    } 
})); 

AbstractAction implementa ActionListener lo que este debe satisfacer la tarea.

Puede ser una mala práctica aplastar tantas líneas de código, pero si está acostumbrado a leerlo, puede ser bastante elegante.

+0

Esto en realidad no le permiten cambie el texto de los botones desde dentro del oyente de acción ... Es un requisito bastante incómodo y no puedo pensar en una manera de mejorar lo que usted dy have. – Cogsy

+0

Entonces, ¿la declaración pública de contador dentro del JButton anónimo y el acceso no calificado desde dentro del ActionListener son correctos? – Tim

+0

Sí, es la única forma en que podrá obtener un "control" en esos campos. Solo recuerde que los campos en la clase interna esconderán campos del mismo nombre declarados en el alcance externo. Esperemos que su compilador/IDE lo advierta explícitamente. – Cogsy

1

No haría algo así en un programa del mundo real, pero teniendo en cuenta los requisitos de su tarea, difícilmente podrá hacerlo mejor.

1

Bueno, hay una manera mucho más elegante de hacerlo.

Desafortunadamente, no es un enfoque Core Java/Swing.

Puede usar SwingBuilder en Groovy para obtener el mismo resultado, utilizando una sintaxis levemente más concisa, p. Ej. pseudo código:

button(text: '' + counter, 
     actionPerformed: {counter--; text = '' + counter + ''}, 
     constraints:BL.SOUTH) 

[http://groovy.codehaus.org/Swing+Builder][1]

estudiantes no usaría esto en su asignación, sin embargo, que he visto realmente se desvían de la norma y son marcados abajo por ella, pero al menos se puede incluirlo como una posible vía para investigar más a fondo.

Creo que lo que tienes en este momento está absolutamente bien.

2

La implementación de varios tipos generalmente es una mala idea.

Raramente es necesario ampliar las clases JComponent, aunque un montón de software y tutoriales incorrectos lo hacen. Un modismo/hack que ha estado ganando terreno recientemente es Double Brace - una clase es solo subclases para darle un inicializador de instancia que actúa como una declaración with de otros idiomas.

En este caso, el código en cuestión se puede escribir como:

JButton button = new JButton(); 
button.addActionListener(new ActionListener() { 
    int counter = 1; 
    { 
     updateText(); 
    } 
    public void actionPerformed(ActionEvent arg0) { 
     --counter; 
     updateText(); 
    } 
    private void updateText() 
     setText(Integer.toString(counter)); 
    } 
}); 
f.getContentPane(button); 

Si se vuelve más complejo, entonces es probable que desee hacer una clase externa (que no implementa ActionListener o se extienden JButton) para manejar los datos.

También tenga en cuenta que debe utilizar el modelo repetitivo EventQueue.invokeLater para asegurarse de que los componentes Swing solo se utilizan en AWT EDT.

+2

updateText no funcionará solo con setText - Creo que necesitas button.setText, o para anidar el oyente dentro de una nueva subclase anónima de JButton. Además, f.getContentPane no toma ningún argumento, creo que te refieres a f.getContentPane.add (botón). –

+0

+1 para no extender JButton por razones de configuración – kleopatra

4

Es bastante feo, pero que podría ser la siguiente utilizando el método ActionListener y una clase anónima:

f.getContentPane().add(new JButton(new AbstractAction("name of button") { 
     private int counter = 0; 

     public void actionPerformed(ActionEvent e) { 
      ((JButton) e.getSource()).setText(Integer.toString(counter--)); 
     } 
    }) { 
     { 
      setText("1"); 
     } 
    }); 

Para hacer más fácil el acceso del mostrador se podía moverlo hacia el nivel superior de su clase y acceder desde ambos lugares donde se llama a setText.

+0

+1. Puede ser 'feo' (su palabra, no la mía), pero me resulta más fácil de entender que el código proporcionado en la pregunta. Supongo que la única pregunta sería si cumple con el criterio de que "JButton y su ActionListener tenían que ser anónimos". AbstractAction implementa ActionListener, pero el instructor puede sentir que no se cumplieron los criterios. –

0

Esta es una de las tareas de mala práctica forzados a hacer en la tarea sólo cosas malas: ;-)

  • uso de ActionListener lugar de acción que es malo en sí mismo
  • , como consecuencia, la determinación del alcance problemas burbujear
    • alcance del contador mayor de lo necesario
    • necesitan tener acceso a botón en el interior del actionPerformed (a través de tipo-yeso o el acceso a la API del objeto circundante)
  • ilegible (aka: unmaintainable) Código

Pero, entonces .. no podemos resistir, podemos ;-) está utilizando una versión de acción, que está limpio (o eso creo) en cuanto a los dos primeros Aquí tema, puede leer como todos los otros ejemplos (y hice trampa, por supuesto: aplicaron por primera vez las clases anónimas, a continuación, dejar que el IDE de hacer la línea

f.add(new JButton(new AbstractAction() { 

     int counter = 1; 
     { // constructor block of action 
      updateName(); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      counter--; 
      updateName(); 
     } 

     private void updateName() { 
      putValue(Action.NAME, "" + counter); 
     } 

    }) { // subclass button 
      { // constructor block button 
      setBackground(Color.PINK); 
     }} 
    ); 
Cuestiones relacionadas