Привязка для изменения пользовательских данных узлов внутри списка? - PullRequest
0 голосов
/ 17 июня 2019

Я создаю приложение JavaFX, в котором у меня есть GridPane из 10 ярлыков, и пользователь может назначать объекты этим ярлыкам для перетаскивания.Я использовал свойство userdata узлов, поэтому, когда пользователь перетаскивает объект на одну метку, он устанавливает этот объект как userdata этой метки.

Теперь я хочу установить привязку для disableProperty кнопки, поэтомукнопка активируется только тогда, когда пользователь «заполнил» все эти метки данными.Я перепробовал несколько вещей, наконец, я пришел к чему-то вроде этого:

FilteredList<Node> emptySlots = gridPane.getChildren().filtered(node -> node.getUserData() == null);
SimpleListProperty<Node> listProperty = new SimpleListProperty<>(emptySlots);
BooleanProperty hasEmptySlots = new SimpleBooleanProperty();
hasEmptySlots.bind(not(listProperty.emptyProperty()));
button.disableProperty().bind(hasEmptySlots);

Но, к сожалению, список emptySlots, похоже, не обновляется при изменении свойства меток userdata.Я уже пытался найти способы обновить этот список, но я нахожу только те способы, которые включают ObservableLists с собственными классами и пользовательскими настройками, когда список создается следующим образом ( отсюда ):

ObservableList<Model> masterData = FXCollections.observableArrayList<>(model ->
    new Observable[]{model.statusProperty()});

Но у меня нет такой возможности.

Кто-нибудь знает, как это заархивировать?

1 Ответ

0 голосов
/ 18 июня 2019

При использовании экстрактор мог бы работать с использованием зеркала из списка children, но, к сожалению, userData не сохраняется в свойстве (то есть не Observable).Чтобы делать то, что вы хотите, вы должны будете использовать другой механизм для хранения объектов вашего пользователя.

Альтернативой использованию userData, в том же духе вашего текущего подхода, является использование Node s properties .Эти свойства хранятся в ObservableMap<Object, Object>, что означает, что их можно наблюдать за изменениями.Чтобы использовать эту опцию, вы все равно захотите использовать экстрактор и зеркально отразить список children.

class Foo {

    private static final String USER_OBJECT_KEY = "USER_OBJECT";

    private final GridPane gridPane = ...;
    private final Button button = ...;

    Foo() {
        ObservableList<Node> mirror = FXCollections.observableArrayList(
                n -> new Observable[]{n.getProperties()}
        );
        Bindings.bindContent(mirror, gridPane.getChildren());
        FilteredList<Node> filtered = mirror.filtered(
                n -> !n.getProperties().containsKey(USER_OBJECT_KEY)
        );
        button.disableProperty(Bindings.isEmpty(filtered));
    }

}

В приведенном выше примере Bindings.isEmpty(ObservableList) вместо того, чтобы заключать наблюдаемый список вListProperty.

Вы также можете рассмотреть возможность перемещения этого состояния в модель.Таким образом, вы не будете связывать состояние приложения с объектами GUI JavaFX (модель не должна ничего знать о представлении).

...