Apr 28, 2017

JavaFX: How to Use Property Events

JavaFX properties provide an addListener method that lets you add event handlers that are called whenever the value of a property changes. You can create two types of property event handlers:

  • A change listener, which is called whenever the value of the property has been recalculated. The change listener is passed three arguments: the property whose value has changed, the previous value of the property, and the new value.

  • An invalidation listener, which is called whenever the value of the property becomes unknown. This event is raised when the value of the property needs to be recalculated, but has not yet been recalculated. An invalidation event listener is passed just one argument: the property object itself.

Change and invalidation listeners are defined by functional interfaces named ChangeListener and InvalidationListener. Because these interfaces are functional interfaces, you can use Lambda expressions to implement them. Here’s how you use a Lambda expression to register a change listener on the text property of a text field named text1:

text1.textProperty().addListener(    (observable, oldvalue, newvalue) ->        // code goes here    );

Here’s an example that registers an invalidation listener:

text1.textProperty().addListener(    (observable) ->        // code goes here    );

The only way the addListener knows whether you are registering a change listener or an invalidation listener is by looking at the arguments you specify for the Lambda expression. If you provide three arguments, addListener registers a change listener. If you provide just one argument, an invalidation listener is installed.

This code listing shows a simple JavaFX application that uses change listeners to vary the size of a rectangle automatically with the size of the stack pane that contains it.

A change listener is registered with the stack pane’s width property so that whenever the width of the stack pane changes, the width of the rectangle is automatically set to half the new width of the stack pane. Likewise, a change listener is registered on the height property to change the rectangle’s height.

import javafx.application.*;import javafx.stage.*;import javafx.scene.*;import javafx.scene.layout.*;import javafx.scene.shape.*;import javafx.scene.paint.*;public class AutoRectangle extends Application{    public static void main(String[] args)    {        launch(args);    }    @Override public void start(Stage primaryStage)    {        Rectangle r = new Rectangle(100,100);    @@a18        r.setFill(Color.LIGHTGRAY);        r.setStroke(Color.BLACK);        r.setStrokeWidth(2);        StackPane p = new StackPane();    @@a23        p.setMinWidth(200);        p.setPrefWidth(200);        p.setMaxWidth(200);        p.setMinHeight(200);        p.setPrefHeight(200);        p.setMaxHeight(200);        p.getChildren().add(r);        p.widthProperty().addListener(    @@a33            (observable, oldvalue, newvalue) ->                  r.setWidth((Double)newvalue/2)            );        p.heightProperty().addListener(    @@a38            (observable, oldvalue, newvalue) ->                  r.setHeight((Double)newvalue/2)            );        Scene scene = new Scene(p);        primaryStage.setScene(scene);        primaryStage.setTitle("Auto Rectangle");        primaryStage.show();    }}

This figure shows this application in action. This figure shows the initial window displayed by the application as well as how the window appears after the user has made the window taller and wider. As you can see, the rectangle has increased in size proportionately.

An example of a responsive website.

The following paragraphs describe the highlights:

  • 18: These lines create a 100×100 rectangle and set the rectangle’s fill color, stroke color, and stroke width.

  • 23: These lines create a stack pane and set its width and height properties.

  • 33: These lines use a Lambda expression to register a change handler with the stack pane’s width parameter. When the stack pane’s width changes, the width of the rectangle is set to one half of the stack pane’s width.

  • 38: These lines use a Lambda expression to register a change handler with the stack pane’s height parameter. When the stack pane’s height changes, the height of the rectangle is set to one half of the stack pane’s height.