Создать BooleanBinding, связанный со значениями List / ObstableList - PullRequest
0 голосов
/ 23 октября 2018

Я пытаюсь создать BooleanBinding, который связан с Button#disableProperty().Моя цель - включить / отключить кнопку ОК при изменении TextField из динамически создаваемого списка панелей.

Это инициализация списка панелей (propertiesList)

<DialogPane prefWidth="900" prefHeight="600" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1">

    <fx:define>
        <FXCollections fx:id="propertiesList" fx:factory="observableArrayList">
            <DatabasePane name="База данни"/>
            <DatabasePane name="База данни 2"/>
        </FXCollections>
    </fx:define>

    ....

    <buttonTypes>
        <ButtonType fx:id="okButtonType" buttonData="OK_DONE" text="Готово" />
        <ButtonType buttonData="CANCEL_CLOSE" text="Затвори" />
    </buttonTypes>

</DialogPane>

Каждый DatabasePane содержит BooleanProperty с именем change и соответствующие методы получения и установки.

В контроллере я создаю коллекцию BooleanProperty из свойств панелей, добавленных в propertiesList

List<BooleanProperty> list = propertiesList.stream()
    .map(pane -> pane.changeProperty())
    .collect(Collectors.toList());

BooleanBinding change = Bindings.createBooleanBinding(() -> true, (BooleanProperty[]) list.toArray());

Button button = (Button) dialogPane.lookupButton(okButtonType);
button.disableProperty().bind(change.not());
java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljavafx.beans.property.BooleanProperty; ([Ljava.lang.Object; is in module java.base of loader 'bootstrap'; [Ljavafx.beans.property.BooleanProperty; is in module javafx.base of loader 'app')

Если я использую ObservableList, ошибок нет, но в сам список вносятся только изменения

ObservableList<BooleanProperty> list = propertiesList.stream()
    .map(pane -> pane.changeProperty())
    .collect(Collectors.toCollection(() -> FXCollections.observableArrayList()));

BooleanBinding change = Bindings.createBooleanBinding(() -> true, list);

Button button = (Button) dialogPane.lookupButton(okButtonType);
button.disableProperty().bind(change.not());

1 Ответ

0 голосов
/ 23 октября 2018

List.toArray() возвращает массив Object[], а не массив BooleanProperty[], но вы приводите массив объекта к BooleanProperty здесь:

(BooleanProperty[]) list.toArray()

Я рекомендую использовать Stream 's toArray метод, принимающий IntFunction:

Observable[] dependencies = propertiesList.stream()
                                          .map(DatabasePane::changeProperty)
                                          .toArray(Observable[]::new);

BooleanBinding change = Bindings.createBooleanBinding(() -> true, dependencies);

Если вы не измените Callable<Boolean> на что-то более значимое, вы также можете опустить зависимости, поскольку привязка никогда не содержитзначение, но true.


BooleanBinding change = Bindings.createBooleanBinding(() -> true, list);

не работает, так как сам список реализует Observable, поэтому вы передаете массив, содержащий только список, параметру varargs, т.е. он эквивалентенв

BooleanBinding change = Bindings.createBooleanBinding(() -> true, new Observable []{ list });

, и только добавленный InvalidationListener добавляется в сам список, а не в его содержимое.

...