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.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s