JavaFX (Property API) Propiedades

Una propiedad en JavaFX en básicamente una clase wrapper que encapsula los campos de un objeto añadiéndoles funcionalidades extras, como: la capacidad notificar los cambios en sus valores o permitir enlaces entre propiedades similares, una propiedad JavaFX puede ser de lectura/escritura o solo-lectura, para cada tipo simple, como: String, Double, etc. tenemos su correspondiente clase wrapper como: StringProperty, DoubleProperty, etc., para tipos complejos tenemos ObjectProperty<T>.

Para crear las propiedades tenemos distintas implementaciones para cada tipo, por ejemplo, para una propiedad de tipo Double contamos con: SimpleDoubleProperty y ReadOnlyDoubleWrapper, la primera crea una propiedad de lectura/escritura y la segunda de solo-lectura, en esta última su valor no puede ser modificado fuera de la clase.

Propiedades de lectura/escritura

Podemos obtener su valor y también cambiarlo si lo deseamos.

IntegerProperty edad = new SimpleIntegerProperty(20);
System.out.println(edad.get());

edad.set(22);
System.out.println(edad.get());

Creamos una propiedad JavaFX de tipo Integer, en el constructor indicamos el valor inicial de la misma, si lo deseamos, disponemos de los métodos get() y getValue() para obtener el valor de la propiedad, el primero devuelve un tipo primitivo int en este caso, el segundo retorna el valor en un objeto Integer, aquellas que no poseen tipo primitivo, por ser referencias, como StringProperty o ObjectProperty<T> devolverán siempre un tipo objeto correspondiente a su propiedad.

Las propiedades también cuentan con los métodos set() y setValue() para cambiar el valor de la propiedad, el primero para tipos primitivos y el segundo para tipos objeto.

Propiedades de solo-lectura

Solo podemos obtener su valor, no modificarlo fuera de la clase, usando la clase wrapper podemos cambiar el valor de la propiedad a lo interno de la clase que la contiene.

ReadOnlyIntegerWrapper idWrapper = new ReadOnlyIntegerWrapper(100);
ReadOnlyIntegerProperty id = idWrapper.getReadOnlyProperty();

System.out.println(id.getValue());

De este modo creamos una propiedad de tipo entero que es de solo lectura, primero creamos una instancia de ReadOnlyIntegerWrapper, y luego a partir de esta instancia obtenemos el objeto ReadOnlyIntegerProperty usando el método getReadOnlyProperty().

La variable idWrapper suele ser usada para cambiar el valor de la propiedad a lo interno de una clase, este cambia se refleja en la propiedad id ya que ambas variables estarán sincronizadas.

Seguro habrás notado que las clases para manejar la API de propiedades JavaFX tienen las siguientes convenciones de nombres: SimpleXXXProperty, ReadOnlyXXXWrapper y ReadOnlyXXXProperty donde XXX se remplaza por el tipo deseado.

image

Estos son los distintos para los que tenemos clases wrappers de propiedades disponibles, a la izquierda vemos el tipo y a la derecha el valor que reemplaza a XXX en las clases.

Propiedades JavaFX Beans

Hemos visto que son las propiedades y como podemos crearlas, ahora veremos como utilizarlas dentro de nuestras clases y la convención utilizada para crear las mismas, para nuestro ejemplo usaremos la clase Person a la cual le añadiremos las siguiente tres propiedades: id, nombre, y fecha.

public class Person {
    
    private final StringProperty nombre = new SimpleStringProperty(this, "nombre", "?");

    public String getNombre() {
        return nombre.get();
    }

    public final void setNombre(String value) {
        nombre.set(value);
    }

    public final StringProperty nombreProperty() {
        return nombre;
    }
    
}

Esta es la definición de la propiedad nombre de tipo StringProperty de lectura/escritura, si vemos la llamada al constructor, SimpleStringProperty(this, "nombre", "?") hemos indicado, primero, una referencia al objeto a que pertenece la propiedad, segundo, el nombre de la propiedad y tercero, el valor inicial de la misma. 

Lo siguiente que vemos son los métodos getNombre() y setNombre(String) usados para obtener y cambiar el valor de la propiedad, estos se marcan como final y siguen la convención de nombres de los JavaBeans, el último método es usado para acceder a la propiedad, este tiene la forma XXXProperty() donde XXX se refiere al nombre de la propiedad.

private final ReadOnlyIntegerWrapper id = new ReadOnlyIntegerWrapper(this, "id", 1);

public final int getId() {
    return id.get();
}

public ReadOnlyIntegerProperty idProperty() {
    return id.getReadOnlyProperty();
}

La propiedad id es de tipo IntegerProperty de solo-lectura por lo que no requerimos el método setter, el método getId() devuelve el valor de la propiedad y idProperty() obtiene la propiedad.

private final ObjectProperty<LocalDate> fecha = new ReadOnlyObjectWrapper<>(this, "fecha");

public final LocalDate getFecha() {
    return fecha.get();
}

public final void setFecha(LocalDate value) {
    fecha.set(value);
}

public ObjectProperty<LocalDate> fechaProperty() {
    return fecha;
}

Esta última propiedad la llamaremos fecha de tipo ObjectProperty<LocalDate>, no indicamos su valor inicial por lo que será nulo, todo lo demás ya lo hemos visto.

Ya tenemos nuestra clase JavaFX Bean lista para ser usada, en cualquier momento podemos obtener información sobre una propiedad consultando los métodos getName() que retorna el nombre y getBean() que obtiene una referencia al objeto al cual pertenece la propiedad, usando getValue() tendremos en valor.

public static void printDetails(ReadOnlyProperty<?> p) {
    String name = p.getName();
    Object value = p.getValue();
    Object bean = p.getBean();

    String beanClassName = (bean == null) ? "null" : bean.getClass().getSimpleName();
    String propClassName = p.getClass().getSimpleName();

    System.out.print(propClassName);
    System.out.print("[Name:" + name);
    System.out.print(", Bean Class:" + beanClassName);
    System.out.println(", Value:" + value + "]");
}

public static void main(String[] args) {

    Person p = new Person();

    System.out.println("--- valores iniciales --- ");

    printDetails(p.idProperty());
    printDetails(p.nombreProperty());
    printDetails(p.fechaProperty());

    System.out.println("--- nuevos valores --- ");

    p.setNombre("Tutor de Programacion");
    p.setFecha(LocalDate.now());

    printDetails(p.idProperty());
    printDetails(p.nombreProperty());
    printDetails(p.fechaProperty());
}

Con este código veremos los detalles de cada una de las propiedades de la clase Person, en primer lugar con los valores iniciales y luego usamos lo setter para cambiar los valores e imprimir nuevamente.

propiedades javafx

Los elementos de la interfaz de usuario de JavaFX usan propiedades, por ejemplo: el control TextField cuenta con varias propiedades, una de ellas text para la cual tenemos los siguientes métodos: text.textProperty(), text.setText(), text.getText(), para manipular el texto que el usuario introduce en este control.

En el siguiente tutorial veremos como podemos estar pendientes a los cambios que se producen en una propiedad JavaFX, para ello aprenderemos a recibir notificaciones con las interfaces InvalidationListener y ChangeListener.

Comentarios

Entradas populares de este blog

Conectar SQL Server con Java

Entrenar OpenCV en Detección de Objetos

Acceso a la webcam con OpenCV

JavaFx 8 Administrar ventanas

Conociendo la clase cv::Mat de OpenCV