Suz*_*ioc 1 java binding javafx javabeans
如何在JavaFX中绑定双向嵌套属性?
例如,我有一个对象p,其具有化子性质prop1和prop2,这反过来又具有属性value两者.
如何将它们双向绑定,以便它们约束相等?
package tests.javafx.beans.binding;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
public class Try_BindNested {
public static class Nested {
private SimpleDoubleProperty value = new SimpleDoubleProperty();
public double getValue() {
return value.get();
}
public void setValue(double value) {
this.value.set(value);
}
public SimpleDoubleProperty valueProperty() {
return value;
}
}
public static class Parent {
private SimpleObjectProperty<Nested> prop1 = new SimpleObjectProperty<Nested>();
private SimpleObjectProperty<Nested> prop2 = new SimpleObjectProperty<Nested>();
public Nested getProp1() {
return prop1.get();
}
public void setProp1(Nested prop1) {
this.prop1.set(prop1);
}
public SimpleObjectProperty<Nested> prop1Property() {
return prop1;
}
public Nested getProp2() {
return prop2.get();
}
public void setProp2(Nested prop1) {
this.prop2.set(prop1);
}
public SimpleObjectProperty<Nested> prop2Property() {
return prop2;
}
}
public static void main(String[] args) {
Parent p = new Parent();
// how to bind bidirectional p.prop1.value = p.prop2.value?
}
}
Run Code Online (Sandbox Code Playgroud)
假设你想处理对"intermediate"属性的更改(即p.prop2.value如果你这样做就更新了p.setProp1(...);)那么就没有办法直接用绑定来做到这一点; 你必须使用一对听众.
使用标准JavaFX属性API:
ObservableDoubleValue prop1Value = Bindings.selectDouble(p.prop1Property(), "value");
ObservableDoubleValue prop2Value = Bindings.selectDouble(p.prop2Property(), "value");
prop1Value.addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> ov, Number oldVal, Number newValue) {
p.getProp2().setValue(newValue);
}
});
prop2Value.addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> ov, Number oldVal, Number newValue) {
p.getProp1().setValue(newValue);
}
});
Run Code Online (Sandbox Code Playgroud)
这些Bindings.select方法有点难看(它们依赖于反射并且不是类型安全的); 此外,在早期的JavaFX 8版本中,如果任何中间属性为null,它们会发出各种警告(尽管这是根据API文档支持的用例).如果这成为问题,您可以查看EasyBind框架.不过,你在这里仍然需要"双听"的习语.
在这种情况下没有"内置"双向绑定的原因是它如何更新属性是不明确的.通常,您可能需要类似的东西p.getProp1().setValue(newVal);,或者您可能想要更改中间属性:p.setProp1(new Nested(newVal));
最后,您可能需要小心使用浮点类型.您最终无法通过上述代码进行无限递归的原因是该set方法在DoubleProperty通知更改侦听器之前检查是否确实发生了更改.如果该值涉及任何计算,则存在舍入错误的风险,从而导致属性检查相等性失败的情况,因此您可能最终得到一个很好的StackOverflowError.如果您的value属性执行的操作比简单地存储值更复杂,那么您可能希望setValue使用容差来保护调用:
private static final double TOLERANCE = 1e-16 ; // or some other suitable small number
prop1Value.addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> ov, Number oldVal, Number newValue) {
if (Math.abs(p.getProp2.getValue() - newVal) > TOLERANCE) {
p.getProp2().setValue(newValue);
}
}
});
Run Code Online (Sandbox Code Playgroud)
而在另一个方向也是如此.
| 归档时间: |
|
| 查看次数: |
1797 次 |
| 最近记录: |