JavaFX Tip 11: Updating Read-Only Properties

Custom controls often feature “read-only” properties. This means that they can not be set from outside the control, not even from their own skin class. It is often the behaviour of a control that leads to a change of the read-only property. In JavaFX this behaviour can be implemented in the control itself and in the skin. So we sometimes end up with a skin wanting to update a read-only property of the control. How can this be done?

Backdoor: Property Map

The solution is quite simple: use the properties map of the control as a backdoor to the control class. The properties map is observable, so if the skin sets a value in the map then the control will be informed and can update the value of the read-only property itself.

The Control Class

The property in the control class might be defined like this:

private final ReadOnlyDoubleWrapper myReadOnly =
   new ReadOnlyDoubleWrapper();

public final ReadOnlyDoubleProperty myReadOnlyProperty() {
    return myReadOnly.getReadOnlyProperty();
}

public final Double getMyReadOnly() {
    return myReadOnly.get();
}

To update the property the control class registers a listener with its own property map and listens for changes to the property called “myReadOnly”:

getProperties().addListener(new MapChangeListener() {
  public void onChanged(Change c) {
    if (c.wasAdded() && "myReadOnly".equals(c.getKey())) {
      if (c.getValueAdded() instanceof Number) {
        myReadOnly.set((Double) c.getValueAdded());
      }
      getProperties().remove("myReadOnly");
    }
  }
});

Important: make sure to use a unique name for the property key or you might end up with naming conflicts. It is good practise to prefix the name with the package name of your control, e.g. com.myframework.myReadOnly.

The Skin Class

Now the skin class can update the property by setting the property value in the control’s property map:

getSkinnable().getProperties().put("myReadOnly", 42);
About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s