У меня проблема с использованием Bindings.when.then.otherwise.
Вот простой пример:
public class Controller implements Initializable {
@FXML
private SubController subPaneController;
@FXML
private Label sum;
// Simple flag, ofc I can use any condition as "when" instead of this.
private BooleanProperty subPaneLoaded = new SimpleBooleanProperty();
@Override
public void initialize(URL location, ResourceBundle resources) {
// ofc NPE since subPane is not yet initialized
//sum.textProperty().bind(subPaneController.sumBinding().asString());
// but here the "then" is evaluated even if "when" is false
sum.textProperty().bind(Bindings.when(subPaneLoaded)
.then(subPaneController.sumBinding().asString()) // and NPE here at evaluation.
.otherwise(""));
}
}
public class SubController {
/**
* Calculates the sum of a few properties used in this controller.
*/
IntegerBinding sumBinding() {
return Bindings.createIntegerBinding(() -> 0);
}
}
Проблема в том, что при ответе здесьтогда или в противном случае оценивается независимо от результата когда.
Я действительно не могу использовать Bindings.select() или, по крайней мере, мне не удалось заставить его работать.
Мой субконтроллер инициализируется, когда этот модуль открывается нажатием кнопки. Я хочу, чтобы каждое изменение, сделанное в этом модуле, отображалось в главном представлении как текст метки и, конечно же, обновлялось реальный, поэтому я хочу использовать только что показанную реализацию.
Если у вас есть какие-либо другие предложения, которые можно решить для получения живого обновления без NPE, я буду признателен.
Легкая привязка не является для меня решением, поскольку я не могу использовать эту стороннюю структуру.
Я использую java 1.8.0_172
умеешь задавать хороший вопрос (с минимальный воспроизводимый пример) - пожалуйста!




У вас есть 2 способа:
When - это просто API-интерфейс для привязки, который удобен для слушателей. Если поведение вас не устраивает 1, создайте собственное:
subPaneLoaded.addListener(new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
sum.textProperty().bind(subPaneController.sumBinding().asString());
subPaneLoaded.removeListener(this);
}
});
Когда SubController готов (при условии, что вы хорошо контролируете subPaneLoaded), вы регистрируете привязку для метки, которая теперь гарантированно не равна нулю. Затем вы также удалите привязку с subPaneLoaded, потому что он выполнил свою работу.
Вы можете настроить привязку в методе контроллера initialize():
public class SubController {
@FXML
public void initialize() {
sum.textProperty().bind(sumBinding().asString());
}
IntegerBinding sumBinding() {
return Bindings.createIntegerBinding(() -> 0);
}
}
Этот метод вызывается при загрузке содержимого FXML (см. Введение в FXML), что также должно избегать NPE. Вам просто понадобится способ сделать sum доступным для него.
Я думаю, что второй подход чище. Одноразовый слушатель - это немного странно, но все же нормально.
1 Поведение нетерпеливой оценки не подходит большинству пользователей, поэтому в будущем его планируется изменить.
Эти решения являются более или менее временными, я действительно не хочу использовать второе решение, даже если оно чище, потому что мой SubController не должен знать о метке суммы, поскольку это не единственный контроллер, который добавляет информацию к этой метке. . Первый подход может быть прекрасным, но, как вы упомянули, использование единственного прослушивателя времени немного странно.
@Sunflame Любое решение будет обходным путем, поскольку мы не можем изменить поведение When прямо сейчас, и вы также запросили «любое другое предложение», что в основном означает обходные пути. Без минимальный воспроизводимый пример это все, что я могу предложить.
Не могли бы вы показать нам сообщение об ошибке / трассировке стека?