JavaFX InvalidationListener y ChangeListener

Las propiedades JavaFX cuentan con el método addListener() que podemos usar para registrar un método que será notificado cuando el valor de una propiedad cambie, la sobrecarga de este método nos permite utilizar dos interfaces, ChangeListener y InvalidationListener, para indicar cual será el método que recibirá las notificaciones, cuando ya no deseemos recibir notificaciones usaremos removeListener().

Estas son las diferentes formas como podemos registrar un Listener.

IntegerProperty age = new SimpleIntegerProperty();

// usando Java 8 Method reference
age.addListener(JavaFXProperty::invalidated);

// con clase anonima
age.addListener(new InvalidationListener() {
      @Override
      public void invalidated(Observable observable) {
          System.out.println("Property is invalid.");
      }
});
  
// este utiliza Java 8 Lambdas
age.addListener((Observable observable) -> {
      System.out.println("Property is invalid.");
});

Para la primera forma se requiere el método publico estático invalidated(Observable o) que se encuentre en nuestra clase JavaFXProperty para cumplir con JavaFXProperty::invalidated.

public static void invalidated(Observable prop) {
    System.out.println("Property is invalid.");
}

Para nuestra serie de ejemplos usaremos el primer método, igual puedes usar el que prefieras.

Usando InvalidationListener

La interface InvalidationListener nos permite recibir notificaciones cuando el valor de una propiedad se cambia de estado inválido a válido, al llamar al método set o setValue se envía la notificación.

IntegerProperty age = new SimpleIntegerProperty();

InvalidationListener listener = JavaFXProperty::invalidated; 
age.addListener(listener);

age.set(100);

age.removeListener(listener);

En este ejemplo vemos como usar addListener y removeListener para registrar y luego quitar el InvalidationListener, cuando se ejecute age.set(100) el InvalidationListener recibirá la notificación, al ejecutar veremos en la consola de salida:

Property is invalid.

Debemos tener presente que la notificación se envía solo cuando la propiedad cambia de estado, llamar consecutivamente al método setter no provocará este cambio, ejemplo:

IntegerProperty age = new SimpleIntegerProperty();

InvalidationListener listener = JavaFXProperty::invalidated;
age.addListener(listener);

age.set(100);
age.set(101);
age.set(102);

age.removeListener(listener);

Este código solo producirá una notificación, para provocar el cambio de estado debemos llamar a método get() o getValue() de este modo la siguiente llamada a set o setValue producirá la notificación.

IntegerProperty age = new SimpleIntegerProperty();
age.addListener(JavaFXProperty::invalidated);

age.set(100);

age.get(); 
age.set(101);

age.get();
age.set(102);

Con este código recibiremos tres notificaciones.

Usando ChangeListener

Utilizamos esta interface para recibir notificaciones cuando cambia el valor de una propiedad, a diferencia del anterior esta interface recibe la notificación cada vez se cambia el valor de la propiedad JavaFX usando el método set o setValue, el método change() de esta interface recibe tres valores, primero una referencia a la propiedad, segundo el valor antiguo y tercero el valor nuevo de la propiedad.

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ObservableValue;

public class JavaFXProperty {

    public static void changed(
            ObservableValue<? extends Number> prop,
            Number oldValue, Number newValue) {

        System.out.print("Property changed: ");
        System.out.println("old = " + oldValue + ", new = " + newValue);
    }

    public static void main(String[] args) {
        IntegerProperty age = new SimpleIntegerProperty(100);
        age.addListener(JavaFXProperty::changed);

        age.set(101);
        age.set(102);
        
        age.setValue(103);
        age.setValue(104);
    }
}

Es este código recibiremos cuatro notificaciones una por cada cambio de valor de la propiedad, el resultado al ejecutar es el siguiente:

javafx listener

Es todo por ahora, en el siguiente tutorial JavaFX veremos los enlaces entre propiedades.

Comentarios

Temas relacionados

Entradas populares de este blog

tkinter Grid

Conectar SQL Server con Java

Controles y Contenedores JavaFX 8 - I

Histogramas OpenCV Python