我正在构建一个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()});
但是我这里没有那个选择。
有人知道如何存档吗?
答案 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对象耦合在一起(模型应该对视图一无所知)。