JavaFX Tutorial - JavaFX Properties








JavaFX properties store the inner state of a control and allow us to listen to state change from JavaFX UI controls.

JavaFX Properties can be bound to one another. Binding behavior allows properties to synchronize their values based on a changed value from another property.

Types of JavaFX Properties

There are two types of JavaFX Properties:

  • Read/Writable
  • Read-Only

JavaFX's properties hold actual values and provide change support, invalidation support, and binding capabilities.

All JavaFX property classes are located in the javafx.beans.property.* package namespace.

The list below are commonly used property classes.

  • javafx.beans.property.SimpleBooleanProperty
  • javafx.beans.property.ReadOnlyBooleanWrapper
  • javafx.beans.property.SimpleintegerProperty
  • javafx.beans.property.ReadOnlyintegerWrapper
  • javafx.beans.property.SimpleDoubleProperty
  • javafx.beans.property.ReadOnlyDoubleWrapper
  • javafx.beans.property.SimpleStringProperty
  • javafx.beans.property.ReadOnlyStringWrapper

The properties with Simple are the read/writable property classes. The properties with ReadOnly are the read-only properties.





Read/Writable Properties

Read/writable properties are property values that can be read and modified.

For example, SimpleStringProperty class creates a string property that is readable and writable to the wrapped string value.

The following code demonstrates an instance of a SimpleStringProperty class and modifies the property via the set() method.

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
/*from   w w  w. j ava  2s .c om*/
public class Main{
  public static void main(String[] args) {
    StringProperty password  = new SimpleStringProperty("java2s.com");
    password.set("example.com");
    System.out.println("Modified StringProperty "  + password.get() );
  }
}

The code above generates the following result.

The code above declared variable password of type StringProperty and assigned to an instance of a SimpleStringProperty class.

The actual value is the string "java2s.com" and it is passed into the constructor of the SimpleStringProperty class.

To read the value back, call the get() method or getValue() method, which returns the actual wrapped value.

To modify the value, call the set() method or setValue() and pass in a string.





Read-Only Properties

To create a read-only property, use the wrapper classes that are prefixed with ReadOnly.

Creating a read-only property needs two steps.

  1. instantiate a read-only wrapper class
  2. invoke the method getReadOnlyProperty() to return a true read-only property object
ReadOnlyStringWrapper userName = new ReadOnlyStringWrapper("java2s.com"); 
ReadOnlyStringProperty readOnlyUserName  = userName.getReadOnlyProperty();

JavaFX JavaBean

The following code shows how to create a JavaFX JavaBean. When building Swing based application we create JavaBean with getter and setter.

Then we have to do the data getting and setting in the UI logic through Swing model class. By creating JavaFX JavaBean with JavaFX properties the JavaFX would do the data binding and finish the data exchange job between domain model class and UI controls.

import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
/*from  w w w.  j av  a2  s  . c o m*/
class User {
  private final static String USERNAME_PROP_NAME = "userName";
  private final ReadOnlyStringWrapper userName;
  private final static String PASSWORD_PROP_NAME = "password";
  private StringProperty password;

  public User() {
    userName = new ReadOnlyStringWrapper(this, USERNAME_PROP_NAME,"fake user");
    password = new SimpleStringProperty(this, PASSWORD_PROP_NAME, "");
  }
  public final String getUserName() {
    return userName.get();
  }

  public ReadOnlyStringProperty userNameProperty() {
    return userName.getReadOnlyProperty();
  }

  public final String getPassword() {
    return password.get();
  }

  public final void setPassword(String password) {
    this.password.set(password);
  }

  public StringProperty passwordProperty() {
    return password;
  }
}

Property Change Event

Property can inform value changed event handler to respond when a property changes.

JavaFX property objects contain an addListener() method, which accept two types of functional interfaces, ChangeListener and invalidationListener.

All JavaFX properties are descendants of the ObservableValue and Observable interfaces, which provide the addListener() methods for ChangeListener and invalidationListener, respectively.

The following code shows how to create a ChangeListener to be registered with a property. As the property's value changes, the change() method will be invoked.

import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
//from   w  w w  .j  a v a2 s.c  o m
public class Main {
  public static void main(String[] args) {
    SimpleIntegerProperty xProperty = new SimpleIntegerProperty(0);

    // Adding a change listener with anonymous inner class
    xProperty.addListener(new ChangeListener<Number>() {
      @Override
      public void changed(ObservableValue<? extends Number> ov, Number oldVal,
          Number newVal) {
        System.out.println("old value:"+oldVal);
        System.out.println("new value:"+newVal);
      }
    });

    // Adding a change listener with lambda expression
    xProperty.addListener((ObservableValue<? extends Number> ov, Number oldVal,
        Number newVal) -> {
          System.out.println("old value:"+oldVal);
          System.out.println("new value:"+newVal);
      });
  }
}

The following code shows how to create an invalidationListener to be registered with a property. As the property's value changes, the invalidated () method will be invoked.

import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.SimpleIntegerProperty;

public class Main {
  public static void main(String[] args) {
    SimpleIntegerProperty xProperty = new SimpleIntegerProperty(0);

    // Adding a invalidation listener (anonymous inner class)
    xProperty.addListener(new InvalidationListener() {
      @Override
      public void invalidated(Observable o) {
        System.out.println(o.toString());
      }
    });

    // Adding a invalidation listener (lambda expression)
    xProperty.addListener((Observable o) -> {
      System.out.println(o.toString());
    });

  }
}

The difference between a ChangeListener and an invalidationListener.

  • Using a ChangeListener we will get the Observable (ObservableValue), the old value, and the new value
  • Using the invalidationListener only gets the Observable object (property)