绑定列表中节点的用户数据更改?

时间:2019-06-17 18:32:16

标签: java javafx observable

我正在构建一个JavaFX应用程序,其中有10个标签的GridPane,并且用户可以通过拖放将对象分配给这些标签。我使用了节点的userdata属性,因此当用户将一个对象拖放到一个标签上时,它将将该对象设置为该标签的userdata。

现在,我想为按钮的disableProperty设置绑定,以便仅当用户用数据“填充”所有这些标签时才启用按钮。我尝试了几件事,最后我想到了这样的东西:

FilteredList<Node> emptySlots = gridPane.getChildren().filtered(node -> node.getUserData() == null);
SimpleListProperty<Node> listProperty = new SimpleListProperty<>(emptySlots);
BooleanProperty hasEmptySlots = new SimpleBooleanProperty();
hasEmptySlots.bind(not(listProperty.emptyProperty()));
button.disableProperty().bind(hasEmptySlots);

但是遗憾的是,当标签的userdata属性更改时,EmptySlots列表似乎没有更新。我已经试图找到更新此列表的方法,但是当创建列表时,只有这样才能找到包含ObservableLists的类和自定义设置(from here):

ObservableList<Model> masterData = FXCollections.observableArrayList<>(model ->
    new Observable[]{model.statusProperty()});

但是我这里没有那个选择。

有人知道如何存档吗?

1 个答案:

答案 0 :(得分:0)

使用an extractor可以使用children列表中的a mirror,但是不幸的是userData没有存储在属性中(即它不是Observable )。要执行您想要的操作,您必须使用其他机制来存储用户的对象。

按照当前方法的精神,使用userData的另一种方法是使用Node的{​​{3}}。这些属性存储在ObservableMap<Object, Object>中,这意味着可以观察到它们的更改。要使用此选项,您仍然需要使用提取器并镜像children列表。

class Foo {

    private static final String USER_OBJECT_KEY = "USER_OBJECT";

    private final GridPane gridPane = ...;
    private final Button button = ...;

    Foo() {
        ObservableList<Node> mirror = FXCollections.observableArrayList(
                n -> new Observable[]{n.getProperties()}
        );
        Bindings.bindContent(mirror, gridPane.getChildren());
        FilteredList<Node> filtered = mirror.filtered(
                n -> !n.getProperties().containsKey(USER_OBJECT_KEY)
        );
        button.disableProperty(Bindings.isEmpty(filtered));
    }

}

以上方法使用properties而不是将可观察列表包装在ListProperty中。

您可能还需要考虑将此状态移到模型中。这样,您可以避免将应用程序的状态与JavaFX GUI对象耦合在一起(模型应该对视图一无所知)。