Hide Javafx implementation from user

master_obz :

So currently I'm working on a project in which I need to launch a quick javafx window within a method. As I don't want to make the class extend Application, my solution was to create an inner class that extends application and launch a javafx window within the method by creating an instance of the inner class and calling launch in the inner class as shown below.

public void createWindow() {
    Fx window = new Fx();
    window.launchWindow();
}

public static class Fx extends Application {
    private void launchWindow() {
        launch();
    }

    public void start(Stage stage) {
        //javafx code
    }
}

The problem is that the inner class has to be public because javafx requires the class that's launched to be public, otherwise it will throw an exception. This causes the problem of users now being able to access the inner class as it's public.

Is it possible to make this private or do some other workaround? Or is there another way I should be going about doing this?

Slaw :

Using Application.launch is not the only way to start the JavaFX runtime, it's just the standard and most used option. Another option is to use Platform.startup(Runnable) (JavaFX 9+). That method will start the JavaFX runtime and invoke the given Runnable on the JavaFX Application Thread.

Platform.startup(() -> {
    Stage stage = new Stage();
    stage.setScene(/* your built scene */);
    stage.show();
});

There are some important things to keep in mind with this setup:

  1. The JavaFX runtime can only be started once per JVM instance; calling startup a second time will result in an IllegalStateException. If your method can be called more than once then you'll need to use Platform.runLater(Runnable) for the second and subsequent calls.

  2. Once you close the last Stage the JavaFX runtime, by default, will exit. Once this happens you cannot start it again unless you restart the entire JVM. To stop this from happening, use Platform.setImplicitExit(false). You will now be responsible for stopping the JavaFX runtime by using Platform.exit().

  3. Using startup bypasses the normal JavaFX lifecycle. In other words, an instance of an Application subclass won't be created and the init(), start(Stage), and stop() methods will not be invoked.

  4. If the JavaFX portion of the application is trivial, note that the runtime will consume resources after it has been started for as long as the application exists. This is true even after you close the last window (and the implicit exit has been set to false). A (possibly non-trivial) workaround to this problem is to launch JavaFX in another process that can be destroyed as needed.


If you're using Java 9+ then another (or at least complimentary) option is to use modules. Put your Application class in a package that is only exported to the javafx.graphics module. This will prevent other modules from accessing your Application class—even if it's public.

module app {
    requires javafx.graphics;
    exports com.example to javafx.graphics;
}

Note: This doesn't stop people from using the classpath or using --add-exports, but that would be "using your library incorrectly" which means the behavior is unspecified.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=113127&siteId=1