【问题标题】:Using ReactFX to resize stage when nodes become invisible?当节点变得不可见时使用 ReactFX 调整舞台大小?
【发布时间】:2015-06-09 14:36:06
【问题描述】:

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

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

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

【问题讨论】:

    标签: javafx javafx-8 rx-java reactfx


    【解决方案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);
    

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

    【讨论】:

    • 你说得对,我应该绑定它。我完全沉浸在 ReactFX 功能中。虽然您说孩子列表是固定的,但LiveList 确实很优雅。谢谢,这很好用。
    • 顺便说一句,如果它不太涉及在 cmets 部分询问。除了使用 managedProperty,您还有什么建议?
    猜你喜欢
    • 2017-07-19
    • 2014-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-21
    • 2015-10-20
    • 2017-08-07
    • 1970-01-01
    相关资源
    最近更新 更多