IllegalStateException при использовании JavaFX Alert в init (), потому что не в потоке приложения FX - PullRequest
0 голосов
/ 05 февраля 2020

Используя этот подход Я пытаюсь реализовать предварительный загрузчик приложения для моего приложения JavaFX. Я хочу загрузить некоторые тяжелые вещи в init(), которые могут вызвать исключение, а затем продолжить с start(). Чтобы обработать исключения, я показываю предупреждение, используя new Alert(AlertType.ERROR).showAndWait();, который показывает некоторые детали пользователю.

public class Test extends Application {
    @Override
    public void init() throws Exception {
        try {
            // dome some heavy stuff here
            throw new Exception();
        } catch (Exception e) {
            new Alert(AlertType.ERROR).showAndWait();
            Platform.exit();
        }
    }

    @Override
    public void start(Stage primaryStage) {
        StackPane root = new StackPane();
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

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

Exception in Application init method
java.lang.reflect.InvocationTargetException
    ... 
Caused by: java.lang.RuntimeException: Exception in Application init method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:895)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.lang.IllegalStateException: Not on FX application thread; currentThread = JavaFX-Launcher
    at javafx.graphics/com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:291)
    ...
    at javafx.controls/javafx.scene.control.Alert.<init>(Alert.java:222)
    at src/gui.Test.init(Test.java:18)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:824)
    ... 2 more
Exception running application gui.Test

Однако мой подход работает нормально, если я перевожу вой код с init() на start().

1 Ответ

0 голосов
/ 06 февраля 2020

В прошлом мне удавалось решить подобные проблемы, заключив лог c в вызов Platform.runLater (). ie:

try {
    [...]
}  catch (Exception e) {
    Platform.runLater(new Runnable() {
    @Override public void run() {
        new Alert(AlertType.ERROR).showAndWait();
        Platform.exit();
    });
}

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

Как взято из вики:

publi c stati c void runLater (Runnable runnable)
Параметры:
runnable - Runnable - метод run которого будет выполняться в потоке приложений JavaFX

...