2015-06-09 3 views
0

У меня есть панель инструментов JavaFX, которая скрывает и показывает компоненты на основе сложных контекстов, поэтому ReactFX - отличная утилита для этого.Использование 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.
EDIT: Например, отфильтровать список детей по их видимым свойством:

// 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.

+0

Вы правы, я должен был связать это. Я все догнал в функциональности ReactFX. И хотя вы правы, что список детей исправлен, 'LiveList' действительно изящный. Спасибо, это работает отлично. – tmn

+0

Btw, если его не слишком заинтересовать, чтобы спросить в разделе комментариев. Что бы вы посоветовали, помимо использования managedProperty? – tmn

+1

@ThomasN. см. обновленный ответ. –