Использование ReactFX для изменения размера стадии, когда узлы становятся невидимыми?
У меня есть панель управления JavaFX, которая скрывает и показывает компоненты, основанные на сложных контекстах, поэтому ReactFX - отличная утилита для этого.
Я создал несколько вложенных замыканий, просматривая каждый узел, создавая EventStream
от каждогоvisibleProperty()
и затем подписать операцию для переключения managedProperty()
и позвонить sizeToScene()
, Хотя мое решение работает, оно не очень чистое. Я чувствую, что должен использовать плоскую карту или что-то в этом роде. Есть ли более чисто реактивный способ реализовать это?
gridPane.getChildren().stream().forEach(c -> {
EventStreams.changesOf(c.visibleProperty()).subscribe(b -> {
c.managedProperty().set(b.getNewValue());
primaryStage.sizeToScene();
});
});
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.