0

我有一个 JavaFX 仪表板,可以根据复杂的上下文隐藏和显示组件,因此 ReactFX 是一个很好的实用程序。

我通过遍历每个节点创建了一些嵌套闭包,创建了一个EventStreamoff each visibleProperty(),然后订阅了一个操作来切换managedProperty()和调用sizeToScene()。虽然我的解决方案有效,但感觉不是很干净。我觉得我应该使用平面地图或其他东西。有没有更纯粹的反应方式来实现这一点?

    gridPane.getChildren().stream().forEach(c -> {
         EventStreams.changesOf(c.visibleProperty()).subscribe(b -> {
             c.managedProperty().set(b.getNewValue());
             primaryStage.sizeToScene();
         });
    });
4

1 回答 1

1

我将假设您的子列表gridPane是固定的,因为在您的代码中您只需遍历它一次。

首先,为什么不将每个孩子绑定 managedProperty到它的visibleProperty?

gridPane.getChildren().stream().forEach(c -> {
    c.managedProperty().bind(c.visibleProperty());
});

要在任何孩子改变其可见性时得到通知,您可以构造并观察一个EventStream

LiveList.map(gridPane.getChildren(), c -> EventStreams.valuesOf(c.visibleProperty()))
        .reduce((es1, es2) -> EventStreams.merge(es1, es2))
        .orElseConst(EventStreams.never()) // for the case of no children
        .values().flatMap(Function.identity())
        .subscribe(b -> primaryStage.sizeToScene());

由于我们假设子列表是固定的,因此您可以使用稍微简单一些的方法:

gridPane.getChildren().stream().map(c -> EventStreams.valuesOf(c.visibleProperty()))
        .reduce((es1, es2) -> EventStreams.merge(es1, es2))
        .orElse(EventStreams.never()) // for the case of no children
        .subscribe(b -> primaryStage.sizeToScene());

综上所述,我会考虑找到一个不会篡改的解决方案managedProperty
编辑:例如,通过可见属性过滤子列表:

// your (fixed) list of children
List<Node> children0 = ...;

// list of children that triggers list changes when children change their visibility
ObservableList<Node> children = FXCollections.observableList(
        children0, ch -> new Observable[]{ ch.visibleProperty() });

// children filtered by visibility
ObservableList<Node> visibleChildren = children.filtered(Node::isVisible);

// bind GridPane's children to visible children
Bindings.bindContent(gridPane.getChildren(), visibleChildren);

visibleChildren由于在 JavaFX 中使用了弱侦听器,您可能需要存储对 的引用以防止它被垃圾收集。

于 2015-06-09T17:31:33.930 回答