Как объявить ключевое слово var для переменной глобально в контроллере MVC

Проблема заключается в том, что вы пытаетесь закрыть Stage из потока другого , чем JavaFX Application Thread. Посмотрев документацию по Stage, вы увидите:

Объекты сцены должны быть сконструированы и изменены в приложении JavaFX Application Thread.

Тема приложения JavaFX создается как часть процесса запуска для среды исполнения JavaFX. Дополнительную информацию см. В классе Application и методе Platform.startup (Runnable).

Тем не менее, Service при запуске выполнит свой Task на фоне . В частности, метод call() для Task выполняется на указанном фоновом потоке. Я только что протестировал попытку закрыть Stage в фоновом потоке, чтобы узнать, что произойдет (независимо от того, будет ли выбрано исключение). Результатом был java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3.

Причина, по которой вы этого не видите, - это не наблюдение за Service за сбой. Вы можете посмотреть ответ на этот вопрос , чтобы посмотреть, как смотреть на провал. Ответ конкретно говорит о Task, но такое же поведение присутствует в Service.

Что вам нужно сделать, чтобы заставить ваш код работать, чтобы убедиться, что close() вызывается в приложении JavaFX Нить. Самый простой способ сделать это - обернуть close() в вызов Platform.runLater(Runnable) .

Service cicle = new Service() {
    @Override
    protected Task createTask() {
        return new Task() {
            volatile boolean waiting = false;

            @Override
            protected Void call() throws Exception {
                Timer.start();
                while (Timer.update() / 1000 < time) {
                    System.out.println(Timer.update())
                }
                Platform.runLater(() -> close()); // wrapped in Platform#runLater
                return null;
            }
        };
    }
};

Вы также можете отменить Service.succeeded() , который всегда будет вызываться в потоке приложений JavaFX (но только в случае успеха Service). В этом случае вы удалите вызов close() из метода call().

Service cicle = new Service() {
    @Override
    protected Task createTask() {
        return new Task() {
            volatile boolean waiting = false;

            @Override
            protected Void call() throws Exception {
                Timer.start();
                while (Timer.update() / 1000 < time) {
                    System.out.println(Timer.update())
                }
                return null;
            }
        };
    }
    @Override
    protected void succeeded() {
        close();
    }

};

Существуют и другие способы: прослушивание свойства state с помощью setOnSucceeded(EventHandler) , и т.д ...

0
задан karan 18 January 2019 в 18:28
поделиться