java - 如何将属性绑定(bind)到列表属性中对象的属性?

标签 java javafx

我有这些类(class):

class Parent {

    BooleanProperty total = new SimpleBooleanProperty();
    SimpleListProperty<Child> children = new SimpleListProperty<>(FXCollections.observableArrayList());
}

class Child {

    BooleanProperty single = new SimpleBooleanProperty();
}

我想要的是,当且仅当所有 child 的 single 都为 false 时,total 才会为 false。换句话说,当且仅当有一个 child 的 single 为真时,total 为真。

我想到了这个绑定(bind)

total.bind(Bindings.createBooleanBinding(() -> {
    return children.stream().filter(c -> c.isSingle()).findAny().isPresent();
}, children.stream().map(c -> c.single).collect(Collectors.toCollection(FXCollections::observableArrayList))));

这是最好的方法吗?

我是否还应该将 total 设置为只读,因为写入绑定(bind)属性会引发异常?

最佳答案

显式绑定(bind)到每个 child 的 single 属性的一个可能问题是,这些绑定(bind)是在调用 total.bind(...) 语句时进行的。因此,如果新的 Child 对象 随后 添加到列表中,这些子对象的 single 属性将不会被观察到,并且绑定(bind)不会失效,如果他们改变了。同样,如果从列表中删除一个子项,它的 single 属性将不会解除绑定(bind)。

作为替代方案,您可以使用 extractor 创建列表.请注意,对于大多数用例,您不需要 ListProperty:直接使用 ObservableList 就足够了。所以你可以这样做

ObservableList<Child> children = 
    FXCollections.observableArrayList(c -> new Observable[]{c.singleProperty()});

如果任何元素 single 属性失效(以及在列表中添加元素或从列表中添加元素时),此列表现在将触发更新通知(并变得无效)。换句话说,列表本身观察每个 child 的 single 属性,如果任何 child 的 single 属性变为无效的。该列表还确保在将新子项添加到列表中时观察新子项的 single 属性,并在从列表中删除子项时停止观察它们。

那么你只需要

total.bind(Bindings.createBooleanBinding(() -> 
    children.stream().anyMatch(Child::isSingle), children);

最后,考虑使用 ReadOnlyBooleanWrapper 以将属性公开为只读。这是整个内容的正确封装版本:

public class Parent {

    private ReadOnlyBooleanWrapper total = new ReadOnlyBooleanWrapper();
    private ObservableList<Child> children = 
        FXCollections.observableArrayList(c -> new Observable[] {c.singleProperty()});

    public Parent() {
        total.bind(Bindings.createBooleanBinding(() -> 
            children.stream().anyMatch(Child::isSingle), children);
    }

    public ReadOnlyBooleanProperty totalProperty() {
        return total.getReadOnlyProperty();
    }

    public ObservableList<Child> getChildren() {
        return children ;
    }

}

public class Child {
    private final BooleanProperty single = new SimpleBooleanProperty();

    public BooleanProperty singleProperty() {
        return single ;
    }

    public final boolean isSingle() {
        return singleProperty().get();
    }

    public final void setSingle(boolean single) {
        singleProperty().set(single);
    }
}

关于java - 如何将属性绑定(bind)到列表属性中对象的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40380097/

相关文章:

java - 按类型 : two @Repository with same name 进行 Spring 注入(inject)

java - 使用 GSON 在序列化 JSON 中输入信息

Java Swing - 调用paintComponent 未清除JPanel?

java - JBoss Drools 检查一次条件

java - 为什么 JavaFx PasswordField 将其内容作为字符串返回?

java - Scala 2.9 桥接方法

java - TextArea Swing与JavaFX选择范围区别

java - Swing 到 Javafx 转换

java - 是否可以使用 JavaFx 创建 Java 小程序?

java - 将接口(interface)实现为匿名内部类时出错