Un Bean que contiene una propiedad compartidas debe mantener una lista de los oyentes de la propiedad, y alertar a dichos oyentes cuando cambie la propiedad. La clase PropertyChangeSupport implementa métodos para añadir y eliminar objetos PropertyChangeListener de una lista, y para lanzar objetos PropertyChangeEvent a dichos oyentes cuando cambia la propiedad compartida. Nuestros Beans pueden descender de esta clase, o utilizar una clase interna.
Un objeto que quiera escuchar los cambios de una propiedad debe poder añadirse o eliminarse de la lista de oyentes del Bean que contiene la propiedad, y responder al método de notificación del evento que señala que la propiedad ha cambiado. Implementando el interface PropertyChangeListener el oyente puede ser añadido a la lista mantenida por el Bean de la propiedad compartida, y como implementa el método PropertyChangeListener.propertyChange(), el oyente puede responder a las notificaciones de cambio de la propiedad.
La clase PropertyChangeEvent encapsula la información del cambio de la propiedad, y es enviada desde la fuente del evento de cambio de propiedad a cada objeto de la lista de oyentes mediante el método propertyChange().
Las siguientes secciones proporcionan los detalles de la implementación de propiedades compartidas.
La clase PropertyChangeSupport implementa dos métodos para añadir y eliminar objetos PropertyChangeListener de una lista de oyentes, e implementa un método que dispara eventos de cambios de propiedad a cada uno de los oyentes de la lista. Nuestro Bean puede descencer de PropertyChangeSupport, o utilizarla como clase interna.
Para implementar una propiedad compartida, seguiremos estos pasos:
private PropertyChangeSupport changes = new PropertyChangeSupport(this);
Este objeto mantiene una lista de oyentes del cambio de propiedad y lanza eventos de cambio de propiedad.
public void addPropertyChangeListener(PropertyChangeListener l) {
changes.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
changes.removePropertyChangeListener(l);
}
public void setLabel(String newLabel) {
String oldLabel = label;
label = newLabel;
sizeToFit();
changes.firePropertyChange("label", oldLabel, newLabel);
}
Observa que setLabel() almacena el valor antiguo de label, porque los dos valores, el nuevo y el antiguo deben ser pasados a firePropertyChange().
public void firePropertyChange(String propertyName,
Object oldValue, Object newValue)
firePropertyChange() convierte sus parámetros en un objeto PropertyChangeEvent, y llama a propertyChange(PropertyChangeEvent pce) de cada oyente registrado. Observa que los valores nuevo y antiguo son tratados como valores Object, por eso si los valores de la propiedad son tipos primitivos como int, se debe utilizar la versión del objeto java.lang.Integer. Observa también que el evento de cambio de propiedad se dispara después de que la propiedad haya cambiado.
Cuando el BeanBox reconoce el patrón de diseño de una propiedad compartida dentro de un Bean, se verá un interface propertyChange cuando se despliege el menú Edit|Events.
Ahora que hemos dada a nuestro Bean la habilidad de lanzar eventos cuando cambia una propiedad, el siguiente paso es crear un oyente.
public abstract void propertyChange(PropertyChangeEvent evt)El Bean fuente llama a este método de notificación de todos los oyentes de su lista de oyentes.
Por eso para hacer que nuestra clase pueda oir y responder a los eventos de cambio de propiedad, debe:
public class MyClass implements java.beans.PropertyChangeListener,
java.io.Serializable {
Para registrar el interés en recibir notificaciones sobre los cambios en una propiedad de un Bean, el Bean oyente llama al método de registro de oyentes del Bean fuente, por ejemplo:
button.addPropertyChangeListener(aButtonListener);
O se puede utilizar una clase adaptador para capturar el evento de cambio de propiedad, y subsecuentemente llamar al método correcto dentro del objeto oyente. Aquí tienes un ejemplo tomado de los ejemplos comentados del fichero beans/demo/sunw/demo/misc/ChangeReporter.java.
OurButton button = new OurButton();
...
PropertyChangeAdapter adapter = new PropertyChangeAdapter();
...
button.addPropertyChangeListener(adapter);
...
class PropertyChangeAdapter implements PropertyChangeListener
{
public void propertyChange(PropertyChangeEvent e)
{
reporter.reportChange(e);
}
}
Detrás de la escena, el BeanBox genera el adaptador de eventos. Este adaptador implementa el interface PropertyChangeListener, y también genera una implementación del método propertyChange() que llama el método ChangeReporter.reportChange(). Aquí tienes el código fuente del adaptador generado:
// Automatically generated event hookup file.
package tmp.sunw.beanbox;
import sunw.demo.misc.ChangeReporter;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
public class ___Hookup_14636f1560 implements
java.beans.PropertyChangeListener, java.io.Serializable {
public void setTarget(sunw.demo.misc.ChangeReporter t) {
target = t;
}
public void propertyChange(java.beans.PropertyChangeEvent arg0) {
target.reportChange(arg0);
}
private sunw.demo.misc.ChangeReporter target;
}
El Bean ChangeReporter no necesita implementar el interface PropertyChangeListener; en su lugar, la clase adaptador generada por el BeanBox implementa PropertyChangeListener, y el método propertyChange() del adaptador llama al método apropiado del objeto fuente (ChangeReporter).
El BeanBox pone las clases de los adaptadores de eventos en el directorio beans/beanbox/tmp/sunw/beanbox.