Привязка JavaFX и значения null

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

у меня есть имущество:

private ObjectProperty<Operation> operation = new SimpleObjectProperty<>(null);

у меня также есть текстовое поле:

@FXML
private Text txtCurrentOperation;

Я хотел бы обязать textProperty поля к значению объекта операции.

моей первой мыслью было использовать FluentAPI с его конструкцией when / then / otherwise, но он с нетерпением оценивается так решение:

Bindings.when(operation.isNotNull())
    .then("null")
    .otherwise(operation.get().getName()));

будет бросать NPE, потому что параметр из otherwise оценивается независимо от того, какой результат when.

моей следующей идеей было как-то использовать лямбду:

txtCurrentOperation.textProperty().bind(() ->
        new SimpleStringProperty(
             operation.isNotNull().get() ? "Null" : operation.get().getName()
            ));

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

некоторые статьи, которые я нашел, предложили использовать "экстремальное" значение для свойства вместо null. Но Операция является сложным и тяжелым компонентом, поэтому нетривиально создавать искусственный экземпляр для представления null. Более того, мне кажется, что это boilercode, то, что механизм привязки предназначен для устранения.

моей следующей попыткой было логически поменять направление привязки и добавить прослушиватель к свойству operation и позволить ему программно обновить поле. Он работает и довольно прост, пока необходимость обновления зависит только от объекта операции примеры:

 operation.addListener((e) -> {
        txtCurrentOperation.setText(operation.isNull().get() ? 
            "Null" : operation.get().getName());
 });
 operation.set(oper);

это относительно просто, но не работает: он бросает "привязанное значение не может быть установлено."исключение, и я не понимаю, почему свойство text элемента управления считается связанным.

у меня кончились идеи. После долгих поисков я все еще не могу решить простую проблему обновления текстового поля по-разному в зависимости от того, является ли источник нулевым или нет.

это кажется настолько простой и повседневной проблемой, что я уверен, что пропустил решение.

2 ответов


если сторонняя библиотека является опцией, проверьте EasyBind. Попробуйте что-то вроде этого:

EasyBind.select(operation)
        .selectObject(Operation::nameProperty)
        .orElse("null");

там же проблема JavaFX JIRA для типа функциональности, предоставляемой EasyBind. Если вы не хотите использовать стороннюю библиотеку, попробуйте Bindings.select:

Bindings.when(operation.isNotNull())
    .then("null")
    .otherwise(Bindings.select(operation, "name"));

имейте в виду, что проверка null Bindings.select не очень эффективно. Есть Jira выпуск для него.


на всякий случай, если кто-то использует не саму Java, а Kotlin. Это хорошая идея, чтобы использовать замечательный tornadofx библиотека. Там вы можете просто использовать operation.select{it.name}. Хотя эта функция, похоже, еще не документирована, поэтому потребовалось некоторое время, чтобы ее обнаружить.