Issue
I want to bind two DoubleProperty bidirectional but not really 1:1, but for example in 1:1.2 proportion.
I need something like:
DoubleProperty x;
DoubleProperty y;
x.bindBidirectional(y.multiply(1.2));
So every time the value of x is set, the y value should be x*1.2 and every time the y value is set the x should be y/1.2
How can I do it?
Solution
Afaik there is nothing already in existance so you need to inplement something like this yourself.
public abstract class BidirectionalBinding<S, T> {
protected final Property<S> property1;
protected final Property<T> property2;
protected boolean calculating = false;
private final InvalidationListener listener;
/**
* Convert value for property 1 to value for property 2
*
* @param value
* @return
*/
protected abstract T convert(S value);
/**
* Convert value for property 2 to value for property 1
*
* @param value
* @return
*/
protected abstract S inverseConvert(T value);
protected BidirectionalBinding(Property<S> property1, Property<T> property2) {
if (property2.isBound() || property1 == null) {
throw new IllegalArgumentException();
}
this.property1 = property1;
this.property2 = property2;
property2.setValue(convert(property1.getValue()));
listener = o -> {
if (!calculating) {
calculating = true;
try {
if (o == property1) {
T value = convert(property1.getValue());
property2.setValue(value);
} else {
S value = inverseConvert(property2.getValue());
property1.setValue(value);
}
} catch (Exception ex) {
dispose();
}
calculating = false;
}
};
property1.addListener(listener);
property2.addListener(listener);
}
public void dispose() {
property1.removeListener(listener);
property2.removeListener(listener);
}
}
DoubleProperty x = new SimpleDoubleProperty(3);
DoubleProperty y = new SimpleDoubleProperty();
final double factor = 1.2;
BidirectionalBinding<Number, Number> binding = new BidirectionalBinding<>(x, y) {
@Override
protected Number convert(Number value) {
return value.doubleValue() * factor;
}
@Override
protected Number inverseConvert(Number value) {
return value.doubleValue() / factor;
}
};
System.out.printf("x = %f; y = %f\n", x.get(), y.get());
x.set(5);
System.out.printf("x = %f; y = %f\n", x.get(), y.get());
y.set(15);
System.out.printf("x = %f; y = %f\n", x.get(), y.get());
Note that this implementation is generalized. If you're dealing with specialized properties, you may want to modify the code to use the primitive types to avoid the conversion to wrapper types...
Answered By - fabian