...)

те рассмотрим следующую ситуацию. СуществуетPane parentPane и здесьPane firstChildPane, secondChildPane, thirdChildPane ..., Дочерние панели добавляются в родительскую панель. Как я могу сделать parentPane видимым только в том случае, если какая-либо из дочерних панелей видима, принимая во внимание, что дочерние панели можно добавлять и удалять динамически без каких-либо ограничений и в любом порядке. Конечно, видимое состояние childPane также может быть изменено в любое время. Можно ли создать динамический Bindings.OR, чтобы я мог динамически добавлять / удалять дочернее видимое свойство? Если да, то как? Если нет, то какие решения используются в таких случаях?

 Linuslabo13 сент. 2017 г., 16:53
 jewelsea13 сент. 2017 г., 20:59

Ответы на вопрос(1)

Решение Вопроса

// list that fires updates if any members change visibility:
ObservableList<Node> children = 
    FXCollections.observableArrayList(n -> new Observable[] {n.visibleProperty()});
// make the new list always contain the same elements as the pane's child list:
Bindings.bindContent(children, parentPane.getChildren());
// filter for visible nodes:
ObservableList<Node> visibleChildren = children.filter(Node::isVisible);
// and now see if it's empty:
BooleanBinding someVisibleChildren = Bindings.isNotEmpty(visibleChildren);
// finally:
parentPane.visibleProperty().bind(someVisibleChildren);

Другой подход заключается в создании собственногоBooleanBinding непосредственно:

Pane parentPane = ... ;

BooleanBinding someVisibleChildren = new BooleanBinding() {


    {
        parentPane.getChildren().forEach(n -> bind(n.visibleProperty()));

        parentPane.getChildren().addListener((Change<? extends Node> c) -> {
            while (c.next()) {
               c.getAddedSubList().forEach(n -> bind(n.visibleProperty()));
               c.getRemoved().forEach(n -> unbind(n.visibleProperty())) ;
            }
        });

        bind(parentPane.getChildren());
    }

    @Override
    public boolean computeValue() {
        return parentPane.getChildren().stream()
            .filter(Node::isVisible)
            .findAny()
            .isPresent();
    }
}

parentPane.visibleProperty().bind(someVisibleChildren);
 Itai13 сент. 2017 г., 17:19
Да ... Я не понял, что это было наоборот! Кажется немного нелогичным, что это ненаблюдаемый список, который «привязан» к наблюдаемому (и поэтому наблюдаемый является тем, который можно безопасно изменить), но я думаю, что это единственный способ, который имеет смысл ,
 James_D13 сент. 2017 г., 17:16
@sillyfly Ноchildren здесь не будет изменено напрямую (достаточно просто сделать это локальной переменной или инкапсулировать ее, чтобы ее нельзя было изменить напрямую)
 Itai13 сент. 2017 г., 17:15
Теперь моя очередь комментировать, чтофабричный метод, который вы используете заявляет: «Как только список привязан к ObservableList, список больше не должен изменяться напрямую. Это может привести к неожиданным результатам».bindContentBidirectional кажется более безопасным выбором ...
 James_D13 сент. 2017 г., 17:21
@sillyfly Мне всегда приходится на минуту останавливаться с помощью этого метода, но да, вы можете только связатьв что-то наблюдаемое, которое определяет, каким путем это будет. (Но в любом случае, вы хотитеchildren быть зависимым отparentPane.getChildren()...)

Ваш ответ на вопрос