我在更大规模的应用程序中遇到了这个问题,当源属性的值发生变化时,某些自定义绑定没有被更新。
我设法写了一个简单的类来复制这个问题,我真的不明白为什么会这样。这是一个复制问题的快速测试:
home.blade.php
所以在运行之后我看到了:
import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.ObjectBinding; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; public class TestingBindingsFx { private final ObjectProperty<MyEvent> objectProperty = new SimpleObjectProperty<MyEvent>(this, "objectProperty"); private final BooleanProperty booleanProperty = new SimpleBooleanProperty(this, "booleanProperty"); private ObjectBinding<MyEvent> bindingObj; private BooleanBinding bindingBool; public TestingBindingsFx(ObjectProperty<String> selection) { setupBindings(selection); } private void setupBindings(ObjectProperty<String> selection) { bindingObj = createObjectBinding(selection); bindingBool = createBooleanBinding(selection); objectProperty.bind(bindingObj); booleanProperty.bind(bindingBool); } private static ObjectBinding<MyEvent> createObjectBinding(ObjectProperty<String> selection) { return new ObjectBinding<MyEvent>() { { super.bind(selection); } @Override protected MyEvent computeValue() { System.out.println("createObjectBinding called"); MyEvent ve = selection.get() == null ? MyEvent.EVENT1 : MyEvent.EVENT2; return ve; } }; } private static BooleanBinding createBooleanBinding(ObjectProperty<String> selection) { return new BooleanBinding() { { super.bind(selection); } @Override protected boolean computeValue() { System.out.println("createBooleanBinding called"); return selection.get() == null ? true : false; } }; } public static void main(String[] args) { ObjClass objclass = new ObjClass(); System.out.println("Instantiating TestingBindingsFx..."); TestingBindingsFx fx = new TestingBindingsFx(objclass.selection); objclass.selection.addListener(new ChangeListener<String>() { @Override public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { System.out.println("changed " + oldValue + "->" + newValue); } }); System.out.println("Changing selection property values..."); objclass.selection.set("Test 1"); objclass.selection.set("Test 2"); } enum MyEvent { EVENT1, EVENT2; } static class ObjClass { public final ObjectProperty<String> selection = new SimpleObjectProperty<String>(this, "selection"); } }
我希望看到类似的内容:
Instantiating TestingBindingsFx... createObjectBinding called createBooleanBinding called Changing selection property values... changed null->Test 1 changed Test 1->Test 2
Instantiating TestingBindingsFx...
createObjectBinding called
createBooleanBinding called
Changing selection property values...
changed null->Test 1
createObjectBinding called
createBooleanBinding called
changed Test 1->Test 2
createObjectBinding called
createBooleanBinding called
正在按预期工作(只是将其放在那里进行验证),并且每次更改选择属性的值时都会调用它。
但是自定义绑定在第一次使用之后永远不会更新,看着我无法理解的代码。起初我以为它可能与弱引用有关,但我甚至将绑定对象转换为类级变量但没有变化。
我觉得我可能会遗漏一些关键的东西,但是看了这段代码2个小时之后我就看不出原因了。 在我的实际应用程序中,它更加奇怪,因为其中一个自定义绑定实际上工作正常。
答案 0 :(得分:3)
这是因为JavaFX非常懒惰。
如果依赖项无效,则绑定将被视为无效,并且InvalidationListener
会被通知潜在的更改。除非您添加ChangeListener
或使用get
来检索值,否则永远不会使用computeValue
方法,因为有#34;没有人想知道新值&#34 ;。这可以提高性能。
使用InvalidationListener
完成绑定属性,并且属性也会被懒惰地刷新。
你可以,例如将更改侦听器添加到属性以在每次绑定失效时强制重新计算值:
private void setupBindings(ObjectProperty<String> selection) {
bindingObj = createObjectBinding(selection);
bindingBool = createBooleanBinding(selection);
objectProperty.bind(bindingObj);
booleanProperty.bind(bindingBool);
objectProperty.addListener((a,b,c)-> {});
booleanProperty.addListener((a,b,c)-> {});
}