JavaFx:绑定号码双向 add/multiply/
JavaFx: Bind number bidirectional with add/multiply/
我想绑定两个 DoubleProperty 双向但不是真的 1:1,但是例如 1:1.2 比例。
我需要这样的东西:
DoubleProperty x;
DoubleProperty y;
x.bindBidirectional(y.multiply(1.2));
所以每次设置x的值,y的值应该是x*1.2
每次设置 y 值时,x 应该是 y/1.2
我该怎么做?
据我所知,目前还没有任何东西存在,因此您需要自己实施类似的东西。
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());
请注意,此实现是通用的。如果您正在处理专门的属性,您可能需要修改代码以使用原始类型以避免转换为包装类型...
我想绑定两个 DoubleProperty 双向但不是真的 1:1,但是例如 1:1.2 比例。
我需要这样的东西:
DoubleProperty x;
DoubleProperty y;
x.bindBidirectional(y.multiply(1.2));
所以每次设置x的值,y的值应该是x*1.2 每次设置 y 值时,x 应该是 y/1.2
我该怎么做?
据我所知,目前还没有任何东西存在,因此您需要自己实施类似的东西。
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());
请注意,此实现是通用的。如果您正在处理专门的属性,您可能需要修改代码以使用原始类型以避免转换为包装类型...