javafx

Properties & Observable

Remarks#

Properties are observable and listeners can be added to them. They are consistently used for properties of Nodes.

Types of properties and naming

Standard properties

Depending on the type of the property, there are up to 3 methods for a single property. Let <property> denote the name of a property and <Property> the name of the property with an uppercase first letter. And let T be the type of the property; for primitive wrappers we use the primitive type here, e.g. String for StringProperty and double for ReadOnlyDoubleProperty.

Method name Parameters Return type Purpose
<property>Property () The property itself, e.g.
DoubleProperty, ReadOnlyStringProperty, ObjectProperty<VPos>
return the property itself for adding listeners / binding
get<Property> () T return the value wrapped in the property
set<Property> (T) void set the value of the property

Note that the setter does not exist for readonly properties.

Readonly list properties

Readonly list properties are properties that provide only a getter method. The type of such a property is ObservableList, preferably with a type agrument specified. The value of this property never changes; the content of the ObservableList may be changed instead.

Readonly map properties

Similar to readonly list properties readonly map properties only provide a getter and the content may be modified instead of the property value. The getter returns a ObservableMap.

StringProperty example

The following example shows the declaration of a property (StringProperty in this case) and demonstrates how to add a ChangeListener to it.

import java.text.MessageFormat;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;

public class Person {

    private final StringProperty name = new SimpleStringProperty();

    public final String getName() {
        return this.name.get();
    }

    public final void setName(String value) {
        this.name.set(value);
    }

    public final StringProperty nameProperty() {
        return this.name;
    }
    
    public static void main(String[] args) {
        Person person = new Person();
        person.nameProperty().addListener(new ChangeListener<String>() {

            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                System.out.println(MessageFormat.format("The name changed from \"{0}\" to \"{1}\"", oldValue, newValue));
            }
            
        });
        
        person.setName("Anakin Skywalker");
        person.setName("Darth Vader");
    }
    
}

ReadOnlyIntegerProperty example

This example shows how to use a readonly wrapper property to create a property that cannot be written to. In this case cost and price can be modified, but profit will always be price - cost.

import java.text.MessageFormat;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ReadOnlyIntegerProperty;
import javafx.beans.property.ReadOnlyIntegerWrapper;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;

public class Product {
    
    private final IntegerProperty price = new SimpleIntegerProperty();
    private final IntegerProperty cost = new SimpleIntegerProperty();
    private final ReadOnlyIntegerWrapper profit = new ReadOnlyIntegerWrapper();

    public Product() {
        // the property itself can be written to
        profit.bind(price.subtract(cost));
    }

    public final int getCost() {
        return this.cost.get();
    }

    public final void setCost(int value) {
        this.cost.set(value);
    }

    public final IntegerProperty costProperty() {
        return this.cost;
    }

    public final int getPrice() {
        return this.price.get();
    }

    public final void setPrice(int value) {
        this.price.set(value);
    }

    public final IntegerProperty priceProperty() {
        return this.price;
    }

    public final int getProfit() {
        return this.profit.get();
    }

    public final ReadOnlyIntegerProperty profitProperty() {
        // return a readonly view of the property
        return this.profit.getReadOnlyProperty();
    }
    
    public static void main(String[] args) {
        Product product = new Product();
        product.profitProperty().addListener(new ChangeListener<Number>() {

            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                System.out.println(MessageFormat.format("The profit changed from {0}$ to {1}$", oldValue, newValue));
            }
        
        });
        product.setCost(40);
        product.setPrice(50);
        product.setCost(20);
        product.setPrice(30);
    }
    
}

This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow