Category: JavaFX
Running and controlling JavaFX applications from regular Java
The concept for JavaFX seems to be that your JavaFX Application is the control center for everything. But what if you would like to run an application as a new screen and to be able to run multiple applications and the same application multiple times? This turns out to be difficult. I spent most of a day trying to figure out how to do it and I think that I came up with a reasonable solution and so wanted to share.
Here is the main utility class and method. You create an application that you want to display i.e. x = new MyApplication(). Then you just call JavaFXUtil.runApplication(…). This will make sure JavaFX is initialized, start your application and block until it is ready to be accessed externally.
public class JavaFXUtil { public static void runApplication(final Application application) throws InterruptedException { InitializeFXApplication.initializeJavaFX(); final WaitObject wait = new WaitObject(); Platform.runLater( new Runnable() { @Override public void run() { try { application.init(); Stage stage = new Stage(); application.start(stage); wait.ready(); } catch (Exception ex) { Logger.getLogger(JavaFXUtil.class.getName()).log(Level.SEVERE, null, ex); } } }); wait.waitUntilReady(); } private JavaFXUtil() { } }
This utility function depends on two other helper classes:
public class InitializeFXApplication extends Application { private static boolean started = false; private static WaitObject wait = new WaitObject(); @Override public void start(Stage stage) throws Exception { started = true; wait.ready(); } public static void initializeJavaFX() throws InterruptedException { if (started) { return; } new Thread() { @Override public void run() { Application.launch(InitializeFXApplication.class); } }.start(); wait.waitUntilReady(); Logger.getLogger(InitializeFXApplication.class.getName()).log(Level.INFO, "JavaFX initialized"); } }
This is the class that makes sure JavaFX environment is initialized.
public class WaitObject { private CountDownLatch latch = new CountDownLatch(1); public void ready() { latch.countDown(); } public void waitUntilReady() throws InterruptedException { latch.await(); } public boolean isReady() { return latch.getCount() == 0; } }
This is just a helper object to manage waiting for resources to be available.