Core Java

JavaFX Tip 5: Be Observable

Even in this time of total NSA surveillance it is still a good idea to implement your JavaFX controls with observability in mind. This is easy to achieve in JavaFX especially compared to Swing.

The Old Days

Coming from Swing I was used to spending a lot of energy and time on making custom controls observable. It usually required adding methods to add and remove listeners of a certain type. This listener type was a new interface, the single method of that interface accepted a new event object. To send this event object the control had to “fire” it inside my custom control, so I ended up writing fireXYZ() methods. A lot of work only to let somebody know that some aspect of the control’s state has changed.

The New Age

In JavaFX observability can be achieved much more easily by using properties and observable collections. In the FlexGanttFX framework almost every attribute of its controls are properties and all collections are created via the FXCollections class, which returns observable collections. This makes a lot of sense because the total of the attributes of each control define its state and this state needs to be observable so that other parts of the application (especially other controls) can react to state changes.

Boilerplate Code

The downside of using properties is that you end up writing a lot of boilerplate code but still much less than in Swing. In the case of a boolean property it will look like this:

public final BooleanProperty showStuff =
     new SimpleBooleanProperty(this, "showStuff", true);

public final BooleanProperty showStuffProperty() {
   return showStuff;
}

public final boolean isShowStuff() {
   return showStuff.get();
}

public final void setShowStuff(boolean show) {
   showStuff.set(show);
}

And yes, you should follow exactly this coding convention. For a property called xxx provide a property accessor method called xxxProperty(), a setter called setXXX() and a getter called getXXX(). This is the way it is used throughout JavaFX and you should stick to it.

When working with collections you typically end up with at least this code:

private final ObservableList<String> names =
     FXCollections.observableArrayList();

public final ObservableList<String> getNames() {
   return names;
}

In the JavaFX core controls collections are often stored in a property so that the whole collection can be replaced by a new collection. So far I haven’t really seen a strong requirement for this in my controls and not doing so means I do’t have to write property listeners for this case.

Listeners

Now that our control attributes are properties we can easily react to state changes by adding listeners to them (using lambda expressions).

myControl.showStuffProperty().
   addListener(it -> showStuffChanged());

myControl.getNames().
   addListener((Observable observable) -> namesChanged());

Conclusion

When designing your own custom control expose its state in the control class via properties and observable collections. By doing so everyone will be able to observe the state of your controls in a way that is consistent with the entire JavaFX framework and that will enable other developers to seamlessly integrate their controls / their application with your controls.

Reference: JAVAFX TIP 5: BE OBSERVABLE from our JCG partner Dirk Lemmermann at the Pixel Perfect blog.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button