-1

Using this approach I am trying to implement an application preloader for my JavaFX application. I want to load some heavy stuff in init() which may throw an exception and then continue with start(). To handle the exceptions I am showing an alert using new Alert(AlertType.ERROR).showAndWait(); that shows some details to the user.

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);
    }
}

But this results in the alert not showing up and generating the following stack trace (see full stacktrace here):

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

However my approach works fine if I move the howl code from init() to start().

Zoffin
  • 3
  • 4
  • Here is a different approach you can take to load data. https://stackoverflow.com/questions/59938519/multi-threading-from-preloader-javafx/59940124#59940124 – SedJ601 Feb 05 '20 at 17:05
  • please read the api doc .. hint: alert must be called in the fx application thread, init is off that thread – kleopatra Feb 05 '20 at 23:19

1 Answers1

0

In the past I've been able to solve this kind of issues with wrapping the logic in a Platform.runLater() call. ie:

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

I use this approach every time I need to do some work that's not directly related to what's going on in the interface.

As taken from the wiki :

public static void runLater(Runnable runnable)
Parameters:
runnable - the Runnable whose run method will be executed on the JavaFX Application Thread

Brenin
  • 195
  • 1
  • 2
  • 16