JavaFX自定义绑定不起作用
我在一个更大规模的应用程序中遇到了这个问题,其中一些自定义绑定在源属性的值更改时没有更新 我设法写了一个简单的类来复制这个问题,我真的不明白为什么会发生这种情况。下面是一个复制问题的快速测试:JavaFX自定义绑定不起作用,java,javafx,javafx-8,Java,Javafx,Javafx 8,我在一个更大规模的应用程序中遇到了这个问题,其中一些自定义绑定在源属性的值更改时没有更新 我设法写了一个简单的类来复制这个问题,我真的不明白为什么会发生这种情况。下面是一个复制问题的快速测试: import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.ObjectBinding; import javafx.beans.property.BooleanProperty; import javafx.beans.
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");
}
}
当我期望看到这样的东西时:
ChangeListener
正在按预期工作(只是为了验证而放在那里),每次我更改selection属性的值时都会调用它
但是自定义绑定在第一次更新之后就再也不会更新了,而且查看代码我不明白为什么。起初我认为它可能与弱引用有关,但我甚至将绑定对象转换为类级变量,但没有任何更改
我觉得我可能遗漏了一些关键的东西,但是在看了两个小时的代码后,我不明白为什么。
在我的实际应用程序中,更奇怪的是,其中一个自定义绑定实际上工作得很好。这是因为JavaFX非常懒惰 如果依赖项无效,绑定将被标记为无效,并且
invalizationlistener
s将收到潜在更改的通知。除非添加ChangeListener
s或使用get
检索值,否则永远不会使用computeValue
方法,因为“没有人想知道新值”。这可以提高性能
绑定属性是使用invalizationlistener
完成的,属性也会被延迟刷新
例如,您可以将更改侦听器添加到属性,以便在每次绑定无效时强制重新计算值:
private void设置绑定(ObjectProperty选择){
bindingObj=createObjectBinding(选择);
bindingBool=createBooleanBinding(选择);
bind(bindingObj);
booleanProperty.bind(bindingBool);
addListener((a,b,c)->{});
addListener((a,b,c)->{});
}
Bingo,就是这样!我知道我遗漏了一些简单的东西,我太专注于computeValue而没有被调用,以至于完全忘记了绑定的懒散本质。我不需要强制重新计算,懒散是很好的,在更改源属性值后,我只是缺少读取测试代码中的目标属性。谢谢你的快速回答。
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