Module MaterialFX

Interface SynchronizedProperty<T>

Type Parameters:
T - the type of the wrapped value
All Superinterfaces:
Observable, ObservableValue<T>, Property<T>, ReadOnlyProperty<T>, WritableValue<T>
All Known Implementing Classes:
SynchronizedBooleanProperty, SynchronizedDoubleProperty, SynchronizedFloatProperty, SynchronizedIntegerProperty, SynchronizedLongProperty, SynchronizedObjectProperty, SynchronizedStringProperty

public interface SynchronizedProperty<T> extends Property<T>
Public API of every synchronized property.

Extends Property.

A synchronized property is a property that doesn't immediately fire a change event when it changes, but it waits for some other observable. We could say that a synchronized property, "synchronized" to another observable, acts "atomically" in terms of changes/change listeners/invalidation listeners. Let's see an example to better understand what I mean:

 
      // Let's say we have two properties dependant on each other
      // This means that when one changes the other has to change and
      // when a change event is caught with a listener both should be updated!
      // In case of JavaFX properties...
      IntegerProperty propertyA = new SimpleIntegerProperty();
      IntegerProperty propertyB = new SimpleIntegerProperty();
      propertyA.addListener((ob, ol, nw) -> System.out.println("B is: " + propertyB.get()));
      propertyB.addListener((ob, ol, nw) -> System.out.println("A is: " + propertyA.get()));

      // Now set the properties with an update method and check the print...
      // Oh, by default integer properties are 0 in JavaFX
      public void update() {
          propertyA.set(8);
          propertyB.set(10);
      }

      // The printed text will be...
      // B is: 0
      // A is: 8

      // Of course right? That's how JavaFX properties and listeners work, it's obvious
      // Well this behavior is not ideal when for example we work with selection models because
      // the selected index and item are strictly connected, their update must be "atomic"
      // Let's see with a synchronized property...
      SynchronizedIntegerProperty propertyA = new SynchronizedIntegerProperty();
      IntegerProperty propertyB = new SimpleIntegerProperty(); // The other property can be a generic observable, even of a different type
      propertyA.addListener((ob, ol, nw) -> System.out.println("B is: " + propertyB.get()));
      propertyB.addListener((ob, ol, nw) -> System.out.println("A is: " + propertyA.get()));

      // The update method has to be changed a bit...
      public void update() {
          propertyA.setAndWait(8, propertyB);
          propertyB.set(10);
      }

      // The printed text will be...
      // B is: 10
      // A is: 8

      // That's why they are called "Synchronized" because they wait for some other observable to change as well before
      // firing a change event.
      // Further details can be found in methods documentation, and subclasses
 
 

SynchronizedProperties override the binding mechanism as well because for some reason the default JavaFX implementation doesn't work properly for them and also because the new mechanism is a lot more flexible, a bit more complex though, but you just need to read the new classes' documentation, BindingHelper, BiBindingHelper.
  • Method Details

    • setAndWait

      void setAndWait(T value, ObservableValue<?> observable)
      Sets this property's state to "waiting" then uses ExecutionUtils.executeWhen(Observable, Runnable, boolean, Supplier, boolean) to "awake" the property when the given observable changes.

      Just like JavaFX properties if the new value is the same as the current value the method returns and does nothing.
      Parameters:
      value - the new value of the property
      observable - the observable to wait for
      Throws:
      IllegalArgumentException - if the given observable is the property itself or if the passed observable is another SynchronizedProperty, and it is already waiting for some other observable
      IllegalStateException - if this property is already waiting for another observable
    • isWaiting

      boolean isWaiting()
      Returns:
      whether this property is in waiting state
    • waiting

      Returns:
      the waiting state property as a read only property
    • awake

      void awake()
      Awakes the property by setting waiting() to false.

      This method should never be invoked by the user, the awakening is automatically managed by the property. If for some reason the property stays in waiting state you are probably doing something wrong.