JavaFX Binding (sincronizar propiedades)

En el tutorial anterior hablamos de las Propiedades JavaFX, más específicamente el como crearlas y utilizarlas, en este nuevo tutorial veremos como dos propiedades pueden mantener sus valores sincronizados, es decir, si la propiedad A esta enlazada con la propiedad B cualquier cambio en el valor de B se reflejará en A, no funciona al inverso, a esto se le llama: unidirectional binding, si que el enlace sea en doble vía, es decir, deseamos que cualquier cambio de A se refleje en B y un cambio en B se refleje en A necesitamos un bidirectional binding.

Para crear un enlace en una sola vía usamos el método bind() para crear un enlace en doble vía usaremos bindBidirectional() y cuando deseemos cortar el enlace utilizaremos los métodos unbind() o unbindBidirectional() según corresponda, estos métodos están presentantes en las propiedades JavaFX.

Este es un ejemplo de un unidirectional binding la propiedad progressProperty del control ProgressBar esta enlazada con la propiedad valueProperty del control Slider, al mover el Slider se cambia también el ProgressBar.

enlace en una vía

Slider slider = new Slider(0, 1, 0);

ProgressBar bar = new ProgressBar(0);
bar.setMaxWidth(Double.MAX_VALUE);
bar.progressProperty().bind(slider.valueProperty());

VBox root = new VBox(slider, bar);
root.setPadding(new Insets(10.0));
root.setSpacing(10.0);

Debemos tener presente que no podemos cambiar la propiedad progressProperty usando set/setValue mientras la misma se encuentre enlazada, podemos usar unbind() para terminar el enlace y luego cambiar la propiedad.

En este segundo ejemplo creamos un enlace en doble vía, usaremos dos controles TextField, lo que escribimos en el primero se refleja en el segundo, si cambiamos el texto del segundo también cambia el texto del primero.

enlace en doble vía

TextField tf_1 = new TextField();
TextField tf_2 = new TextField();

tf_1.textProperty().bindBidirectional(tf_2.textProperty());

VBox root = new VBox(tf_1, tf_2);
root.setPadding(new Insets(10.0));
root.setSpacing(10.0);

El enlace no esta restringido a propiedades del mismo tipo, veremos un ejemplo donde enlazamos el elemento seleccionado de un ListView<Integer> al texto de un control Label.

enlace de Integer a String

ListView<Integer> lv = new ListView<>();
lv.getItems().addAll(1, 2, 3, 4, 5);

String txt = "Elemento seleccionado: %d";

Label lbl = new Label();
lbl.textProperty().bind(lv.getSelectionModel()
        .selectedItemProperty().asString(txt));

Usamos getSelectionModel().selectedItemProperty() para acceder a la propiedad que indica cual es el elemento actualmente seleccionado, como este elemento es de tipo Integer y textProperty() requiere un String usamos el método asString() para convertir la propiedad, este método puede ser usado sin parámetros o indicando una cadena que establece el formato para la conversión.

Los enlaces también pueden ser de tipo numérico, NumberBinding, estos nos proveen una serie de operaciones aritméticas que podemos aplicar para recalcular el valor de una propiedad antes de sincronizarla, en el siguiente ejemplo creamos un conversor de unidades, sincronizamos las propiedades value del Slider con text del TextField, pero antes debemos multiplicar por el correspondiente valor para obtener la conversión.

JavaFX multiplicar propiedades con NumberBinding

Slider sliderPies = new Slider(0, 100, 0);
sliderPies.setShowTickMarks(true);
sliderPies.setShowTickLabels(true);

NumberBinding pulgadas = sliderPies.valueProperty().multiply(12);
NumberBinding metros = sliderPies.valueProperty().multiply(.3048);

TextField txtPulgadas = new TextField();
txtPulgadas.textProperty().bind(pulgadas.asString("En pulgadas: %.2f"));

TextField txtMetros = new TextField();
txtMetros.textProperty().bind(metros.asString("En metros: %.2f"));

No solo podemos multiplicar, también tenemos disponible métodos para sumar add(), restar subtract(), dividir divide(), además podemos aplicarlas en combinación para lograr operaciones más complejas, debemos saber que los parámetros de estas operaciones puedes ser un valor constante u otra propiedad siempre que sea del tipo adecuado.

Otro tipo de enlace son los BooleanBinding que nos permiten sincronizar propiedades de tipo booleano, nuestro ejemplo habilita el botón solo cuando se ha escrito algún texto en ambos controles TextField.

JavaFX deshabilitar botón usando enlace BooleanBinding

JavaFX deshabilitar botón usando enlace BooleanBinding

Label lblNombre = new Label("Nombre");
Label lblContrasena = new Label("Contrasena");

TextField tfNombre = new TextField();
PasswordField tfContrasena = new PasswordField();

Button btnEntrar = new Button("Entrar");
btnEntrar.setMaxWidth(Double.MAX_VALUE);

btnEntrar.disableProperty().bind(
        tfNombre.textProperty().isEmpty().or(
                tfContrasena.textProperty().isEmpty()));

Al final del fragmento de código veremos textProperty().isEmpty() esto verifica si la propiedad text está vacía y devuelve un BooleanBinding luego usamos el método or para aplicar una operación lógica con la propiedad text del otro campo de texto, lo que quiere decir que, si el primer o segundo campo de texto está vacío el botón estará deshabilitado.

Como la propiedad del control Button llamada disableProperty es de tipo BooleanProperty le podemos aplicar el BooleanBinding.

Existen otras formas de crear enlaces, una es usando la clase Bindings la cual cuenta con aproximadamente 100 métodos estáticos que podemos utilizar para diversos propósitos, otra manera es utilizar la API a bajo nivel, con ella tenemos mas control por lo que podemos realizar operaciones más complejas, estas formas alternativas de crear enlaces las veremos en próximos tutoriales.

Descargar ejemplos en: GitHub Tutoriales JavaFX

Comentarios

  1. Me ha ayudado mucho, esta explicado de una forma clara y sencilla, Muchas gracias.

    ResponderEliminar
  2. excelente tutorial, el mejor que he visto hasta ahora

    ResponderEliminar
  3. Esta muy bien muchas gracias, me gustaría saber como aplicar binding a los CheckBox, Datepicker, entre otros, gracias un saludo

    ResponderEliminar

Publicar un comentario

Temas relacionados

Entradas populares de este blog

tkinter Grid

Controles y Contenedores JavaFX 8 - I

Conectar SQL Server con Java

tkinter Canvas