I'm trying to run a program using JavaFX. If I was using Swing, I would have one class started by the main method, and have it build the GUI class. That would give me 2 threads, normal thread for an application, and the EventQueue. That would prevent blocking the UI work.
So, I tried to have the class created in the static main method construct the Application class, and then launch it. I got a RuntimeException because the program calling the launch method was not a subclass of Application.
Is there a way to have separation of threads, or does everything have to work inside a the thread given to an Application class?
It's not really different from Swing, both FX and Swing use their own Event dispatch thread.
Take this example that runs 3 applications in one:
with some output like
The initial thread that has the
main
method ends almost immediately, each of the sub - applications continue running on their own thread. The application as a whole ends once all threads are done.The only tricky bit about JavaFX is that it's
launch
method blocks until the app (which runs in it's own thread) is done. You can either let it take over the initialmain
thread and run your other code in a new thread, or move the launch to a new thread to keep the main one free.In JavaFX, I'm guessing in order to prevent the very common threading errors that were present in many Swing applications, the startup process is constrained so that (more or less) the only way to do things forces you to execute the UI code on the FX Application Thread:
In an Oracle JRE, executing
java MyAppStartClass
will (in contrast to a regular Java application), cause an instance ofMyAppStartClass
to be created, the FX Application Thread to be started, and thestart
method of the created instance to be executed on the FX Application Thread. (There is a bit more to it than that, but that's the basic gist.)If you want to support environments that aren't aware of how to execute a JavaFX Application (including many IDEs), you can add a
main
method that forces this to happen, simply by calling the staticApplication.launch()
method:Note there's an overloaded form of
launch
, where you can specify anApplication
subclass, so you could have a different main class (the use cases for this are very few):There are two important features of the
launch
method to be aware of:If you want to have a thread doing work besides the FX Application Thread, the simplest way is to start it directly from the start method:
If you compare this to the standard startup for a Swing application:
the process is kind of inverted compared to Swing. In Swing you (are supposed to) explicitly have the startup method (main) specify that the UI is run on the AWT event dispatch thread, and you can do other stuff in the "current" thread in which main is executed. In JavaFX the startup method (start) is executed on the UI thread, and if you want to do stuff on another thread you explicitly launch one.
Other rules are pretty much the same: UI elements that are part of the scene graph can only be modified on the UI thread, etc. Note JavaFX has a specific concurrency API for managing tasks in a background thread and scheduling UI updates on the FX Application Thread.
Aside:
In theory I suppose you could do something like:
But since that idiom is far from the usual setup, I would not recommend it. Note especially you should not have a main method like this directly in the
Application
subclass, as (I think) an Oracle JRE (or an environment that knows how to run JavaFX Applications) might ignore the main method and just boot up your start method as described at the top of this post.