Bindings are one of the key features of the JavaFX language, because they simplify one´s life tremendously. By reducing the amount of boilerplate code, which is usually needed to keep the objects in an application in-sync, the developer can concentrate on the really important things. (You know, like a cool looking UI.) 😉
Unfortunately Java objects do not provide this capabilities for their fields. That means the boilerplate code has to be written manually. This article will show a solution to bind properties of Java objects.
Overview
Let´s assume, we have a Java class Rectangle with the four properties x, y, width, and height. We want to show the rectangle on the screen using JavaFX script and update its position and size as the properties of the Java object change.
The code of the class Rectangle would be something like this:
1 public class MyRectangle { 2 private int x, y; 3 private int width, height; 4 5 public int getX() { return x; } 6 public void setX(int x) { this.x = x; } 7 public int getY() { return y; } 8 public void setY(int y) { this.y = y; } 9 public int getWidth() { return width; } 10 public void setWidth(int width) { this.width = width; } 11 public int getHeight() { return height; } 12 public void setHeight(int height) { this.height = height; } 13 14 // ... more functionality here 15 }
Code Sample 1: First draft of MyRectangle
What we want the JavaFX script to look like, is this:
1 import javafx.stage.Stage; 2 import javafx.scene.Scene; 3 import javafx.scene.shape.Rectangle; 4 5 Stage { 6 scene: Scene { 7 // ... more attributes here 8 content: Rectangle { 9 x: bind r.x 10 y: bind r.y 11 width: bind r.width 12 height: bind r.height 13 } 14 } 15 }
Code Sample 2: JavaFX program binding the rectangle
This looks simple enough and the only question remaining is: what is “r”? To allow the script to bind to the fields of the Java object, we need to introduce an adapter between the two, which provides a more JavaFX-like interface of the Java class and which will take care of the synchronization. A simplified class-diagram of the three objects is shown in Figure 1:

Class Diagram
The basis interface of the adapter can be defined as follows:
1 public class RectangleAdapter { 2 public-read var x: Integer; 3 public-read var y: Integer; 4 public-read var width: Integer; 5 public-read var height: Integer; 6 7 public-init var javaRectangle: MyRectangle; 8 }
Code Sample 3: First draft of the adapter RectangleAdapter
Only thing left to do is to add the following line to the script in Listing 3. This will create a new instance of RectangleAdapter and its adaptee Rectangle.
Synchronizing with the Java object
Synchronizing the adapter whenever the state of the Java object changes requires some more work. In general there are two possibilities to implement this functionality. The first solution is to make the adapter an observer (or "listener" to speak more Java-like) of the Java object. This is usually the preferred approach, unfortunately it is not always possible. For example, if you are dealing with existing classes, which you cannot change, this approach would be problematic. The second solution, which does not require any changes to the Java class, is to request the current state repeatedly.Synchronizing using the observer-pattern
There are numerous ways to implement the observer-pattern. Since this article is not so much about implementing Java programs, I will use the simplest approach by extending Observable. This is a utility-class, which provides all of the functionality required by the observer-pattern. All we need to do is add the code to initiate the notification of our observers. The class Observable requires two method-calls for that: setChanged() to signal the object has changed and notifyObservers() to start the notification-process. In our code example, I added a small private method startNotification() to bundle both calls and updated the setters. Code sample 4 shows the new version of the class Rectangle.1 import java.util.Observable; 2 3 public class MyRectangle extends Observable { 4 private int x, y; 5 private int width, height; 6 7 public int getX() { return x; } 8 public void setX(int x) { 9 this.x = x; 10 startNotification(); 11 } 12 13 public int getY() { return y; } 14 public void setY(int y) { 15 this.y = y; 16 startNotification(); 17 } 18 19 public int getWidth() { return width; } 20 public void setWidth(int width) { 21 this.width = width; 22 startNotification(); 23 } 24 25 public int getHeight() { return height; } 26 public void setHeight(int height) { 27 this.height = height; 28 startNotification(); 29 } 30 private void startNotification() { 31 setChanged(); 32 notifyObservers(); 33 } 34 35 // ... more functionality here 36 }
Code Sample 4: MyRectangle implementing Observable
To finish this solution, we need our adapter to extend the interface Observer. That requires to implement its method update(), and to register the adapter. The registration is done by calling addObserver() in the onReplace-trigger of the attribute javaRectangle.
The method update() comes with two parameters, which are helpful, if we want to observe more than one object or if we are dealing with different events. But in our code example, we can ignore them. Only thing left to do is pull the new values from javaRectangle and update the attributes of the adapter.
But wait! You have to be careful here. While our Java code can run on any thread, JavaFX Script is picky here. We need to make sure, that the update is done on the right thread, otherwise the bindings and subsequent actions might fail.
JavaFX Script provides a mechanism for this. The method FX.deferAction() takes a simple function as a parameter and makes sure, that it is executed on the right thread. The complete adapter is shown in code sample 5.
1 import java.lang.Object; 2 import java.util.Observable; 3 import java.util.Observer; 4 5 public class RectangleAdapter extends Observer { 6 public-read var x: Integer; 7 public-read var y: Integer; 8 public-read var width: Integer; 9 public-read var height: Integer; 10 11 public-init var javaRectangle: MyRectangle 12 on replace { javaRectangle.addObserver(this); } 13 14 override function update(observable: Observable, arg: Object) { 15 FX.deferAction( 16 function(): Void { 17 x = javaRectangle.getX(); 18 y = javaRectangle.getY(); 19 height = javaRectangle.getHeight(); 20 width = javaRectangle.getWidth(); 21 } 22 ); 23 } 24 }
Code Sample 5: RectangleAdapter implementing Observer
Synchronizing by pulling the state
The second solution does not require any change to the Java class. Let's assume, we do not want to bind to an object of our own Rectangle, but to an instance of java.awt.Rectangle. This class does not provide any mechanisms to observe state-changes. Instead we have to pull the current state on a regular base to notice changes.
The JavaFX class PauseTransition provides exactly the needed functionality. It comes with two main attributes to setup the behavior. The parameter action defines the task, which needs to be executed, and the parameter duration defines the gap between two consecutive calls.
Defining the right value for the duration is probably the toughest part. The best choice depends on the context. If the value is too low, precious CPU cycles are wasted, if the value is too high, the update might come too late. In our example, the duration is set to 10 ms, which ensures smooth animations.
The adapter for the second solution is shown in code sample 6. Note, that we do not have deal with threading in this solution, because the action of the ActionTransition is already executed on the right thread.
1 import java.awt.Rectangle; 2 import javafx.animation.Timeline; 3 import javafx.animation.transition.PauseTransition; 4 5 public class RectangleAdapter { 6 public-read var x: Integer; 7 public-read var y: Integer; 8 public-read var width: Integer; 9 public-read var height: Integer; 10 11 var action: PauseTransition; 12 public-init var javaRectangle: Rectangle 13 on replace { 14 action = PauseTransition { 15 duration: 10ms 16 action: function(): Void { 17 x = javaRectangle.x; 18 y = javaRectangle.y; 19 height = javaRectangle.height; 20 width = javaRectangle.width; 21 } 22 repeatCount: Timeline.INDEFINITE; 23 } 24 action.play(); 25 } 26 27 public function stop() { 28 action.stop(); 29 } 30 }
Code Sample 6: RectangleAdapter pulling the status
Summary
This article presented two solutions to implement a simple binding of a Java object. The first solution is always preferable, because it uses CPU cycles only when an update took place, while the second solution burns cycles even when nothing happens. The second solution is a fall back in cases, where the observer pattern cannot be implemented.