JavaFx: NPE в Bindings.when (). Then (). В противном случае ()

У меня проблема с использованием 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

Не могли бы вы показать нам сообщение об ошибке / трассировке стека?

deHaar 17.12.2018 16:38

умеешь задавать хороший вопрос (с минимальный воспроизводимый пример) - пожалуйста!

kleopatra 17.12.2018 16:59
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
331
1

Ответы 1

У вас есть 2 способа:

1. Слушатель

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, потому что он выполнил свою работу.

2. @FXML initialize ()

Вы можете настроить привязку в методе контроллера 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 18.12.2018 09:21

@Sunflame Любое решение будет обходным путем, поскольку мы не можем изменить поведение When прямо сейчас, и вы также запросили «любое другое предложение», что в основном означает обходные пути. Без минимальный воспроизводимый пример это все, что я могу предложить.

user1803551 18.12.2018 15:36

Другие вопросы по теме