-
Notifications
You must be signed in to change notification settings - Fork 47
Creating a Val or Var Instance
Val
and Var
are created via their respective class' static factory methods. Some are shown below, grouped by the kind of Val
or Var
they create.
- Constant
Val
: Create aVal
whose value never changes: Val.constant(T value)
- Convert an
ObservableValue
into aVal
Val.wrap(ObservableValue dependency)
- Apply some modifications to the dependencies before storing the returned modified value in the
Val
object: -
Val.animate(ObservableValue, BiFunction)
- Create aVal
that gradually transitions to the value of the givenObservableValue
every time that vaue changes. -
Val.combine(ObservableValue<T> dependencies..., resolver)
- Create aVal
that watches the given dependencies and when any one of them changes, run the resolver's code (which depends on the number of dependencies: Function, BiFunction, TriFunction, etc.) and set thisVal
to the returned result Val.conditionOn(ObservableValue<T> observable, ObservableValue<Boolean> condition)
-
Val.create(Supplier, ObservableValue... dependencies)
- Create aVal
whose value gets updated whenever one of the dependencies' values changes. - etc.
- Create a
Val
with suspendability: Val.suspendable(ObservableValue<T> observable)
- Create a regular
Var
object: Var.newSimpleVar(T initialValue)
- Create a mapped
Var
that is bound bidirectionally to another property. When that property changes, thisVar
is set to the result of the applying thepropToVarMapper
function to its value and vice versa: -
Var.mapBidirectionally(ObservableValue<T> observable, Function propToVarMapper, Function varToPropMapper)
/ - Convert a primitive property frequently used by JavaFX Controls to a
Var
(see below for why this is necessary): Var.integerVar()
Var.doubleVar()
Var.floatVar()
Var.longVar()
- Create a
Var
with suspendability: Var.suspendable()
You'll notice that Var has "wrap" methods for primitive-type properties. You may ask, "Why is that needed?" Let's look at the following code:
IntegerProperty simpleIntProp = new SimpleIntegerProperty(4);
Var<Integer> varIntProp = Var.newSimpleVar(6);
// Surprise! Your IDE will flag this as a compile error!
varIntProp.bind(simpleIntProp);
Why the error you ask? It's an implementation problem affecting all Number-related types (Integer
, Double
, Float
, and Long
). Each implements Property<Number>
, not Property<Primitive_Type>
. The only way around this is to use Var<Number>
, which is rather annoying.
IntegerProperty simpleIntProp = new SimpleIntegerProperty(4);
Var<Number> varNumProp = Var.newSimpleVar(6);
// no issue now...
varNumProp.bind(simpleIntProp);
// ...but to get the integer value, now we need to call
int integerValue = varNumProp.getValue().intValue();
Why is this a problem? Because all the objects provided in the JavaFX framework that use primitive number type properties (ScrollPane
, Circle
, etc.) will need to work around this issue. So, to workaround this, Tomas provided the wrap methods for primitive number types:
// Code found in JavaFX provided items like Circle
IntegerProperty anIntProp = new SimpleIntegerProperty(4);
Var<Integer> varIntProp = Var.newSimpleVar(6);
// so a faster way is to use the "integerVar()" method
Var<Integer> anIntPropAsVar = Var.integerVar(anIntProp);
varIntProp.bind(anIntPropAsVar);
Additionally, using Val<Integer>
will not work well when binding bidirectionally. To work around this, one can use a simulated recursion-updating mechanism:
IntegerProperty intProp = new SimpleIntegerProperty(4);
Var<Integer> intVar = Var.newSimpleVar(4);
// use EventStreams to feed the two properties values into one another when any one of them changes.
Subscription simulatedBidirectionalBinding = Subscription.multi(
Val.wrap(intProp).values().feedTo(intVar),
intVar.values().feedTo(intProp)
);