JavaFX with CDI example.
⚠️ In case you have a hi-resolution display and want to run the application on Ubuntu, make sure to pass an environment variable likeGDK_SCALE=2
to the application. Otherwise it will be unscaled. See Issue #643 for more details.
The example application shows how to implement the most important parts of a real world JavaFX application. Most tutorials for JavaFX only show how to create a screen, but there is more than that.
This example has the following features included:
- Based on Java 17 with JavaFX 21
- Maven build
- Github build
- Contexts and Dependency Injection (CDI)
- Structuring an application with sub controllers
- Using tasks for handling long operations
- Blocking UI during task execution
- About dialog showing a version
- Catching unexpected exceptions showing a dialog
- UI test with TestFX
- Maven Archetype
The project is based on Java 17 and JavaFX.
There is a fully configured Maven build that creates a ZIP archive that has a batch file (Windows) and a shell script (Linux) to start the application.
The project is ready configured to be build on Github. Simply copy the project generated by the below archetype to a fresh Github repository and you have an automated build out of the box.
It also sets the necessary arguments in case you want to run some GUI unit tests:
-Djava.awt.headless=true -Dtestfx.robot=glass -Dtestfx.headless=true
-Dprism.order=sw -Dprism.text=t2k -Dtestfx.setup.timeout=2500
You can use @Inject
annotations in your application controllers for injecting services, events and configuration.
@Singleton
@Loggable
public class ChildController implements Initializable {
@FXML
private Label labelResult;
@Inject
private Logger log;
...
}
If you start with JavaFX it's not easy to figure out how to structure a larger application. See the JavafxCdiExampleController.java to see how a parent controller opens a child controller and passes some data to it.
@FXML
public void onOpenChildController(ActionEvent event) {
final NodeControllerPair<ChildController> childCtrlPair =
NodeControllerPair.load(loaderInstance, ChildController.class);
final ChildController childController = childCtrlPair.getController();
childController.setProgressUI(progressUI);
childController.setMessageDisplay(messageDisplay);
borderPaneContent.setCenter(childCtrlPair.getParent());
}
There are often some operations that may take a while. You need to create a task for it. See the LongRunningTaskExample.java on how to do it. The task also emits some status information to the UI and blocks it.
During execution of a long running task you most likely want to block the UI and show some progress indicator.
Use the Maven version from the POM and the Git information inside the project to populate an About dialog.
Sometimes your application will fail and throw an exception. It's a good idea to show something useful to the user (See ExceptionAlert).
Example UI test with TestFX: JavafxCdiExampleTest.java
There is a Maven Archetype available that helps kickstarting your own project based on this code.