JavaFX from the Trenches – Singleton Controllers

My genealogy application, Evidentia, uses a LOT of stages. Those stages are REUSED a LOT of times. In order to reuse the stages in the most efficient way possible (memory and CPU wise), I implemented the good ole Singleton design pattern.

Now this isn’t glamorous, but then “From the Trenches” is about the day to day stuff in JavaFX, so I wanted to share how I chose to implement the pattern at the controller level.

So what were my “requirements”?

  • Needed to reuse the same stages MANY times but with different data initializing the various fields.
  • Needed to reuse the same stages from DIFFERENT parent windows.
  • If the stage had dynamic controls (controls that could appear/disappear depending on how the user utilized it), the stage had to reinitialize itself to a known state, either after use or before reuse.

Pretty typical Java stuff. Here is the boiler plate for almost ALL my controllers:

public class LicenseInstallerController implements Initializable {
// define various @FXML fields to be initialized
    private static Stage myStage = null;
    private static LicenseInstallerController instance = null;
    public static synchronized void show(MyDataObject myData) throws IOException {
        if (myStage == null) {
	    // things that only need to be done once
	    // notice the reference to the Stage "myStage" is saved in a static variable
            URL location = LicenseInstallerController.class
            FXMLLoader loader = new FXMLLoader();
            Scene scene = new Scene((Pane) loader.load(location.openStream()));
	    // by now, I can count on the initiialize() method having been called
	    // and a reference to this controller being storedd in "instance" variable
            myStage = new Stage();
            myStage.setTitle("Evidentia License Installer");
	    // by setting an owner (this case my MASTER" stage), two things happen
	    // 1) shutdown of app closes window, 2) toFront() works as expected
	// HERE is where I put code to return the state of the stage 
        // and its controls to a known state.
	// if you don't clear out text fields, selection indices, etc... 
        // there will be garbage left from the last time show() was called...
	// anything specific to THIS call to show, like initializing text fields with data 
        // from "myData" is done here, just before is called
    public void initialize(URL url, ResourceBundle rb) {
        instance = this;
		// one time initializations to controls happen here
		// remember this is called during the loader.load(),
		// so its only called the FIRST time
	public static LicenseInstallerController getInstance() {
		// yeah I know, NULL check and synchronize are missing...
		// the getInstance() method is seldom used - usually only for
		// message passing between stages
		return instance;

A couple of my own comments:

  • Yes I know, I haven’t protected the instantiation of the instance variable – but in my app I generally know there won’t be multiple threads creating the controller. (I should still go back and clean that up!)
  • I ran into an issue where a stage that had lost focus (not on top, was blurred out) still had popup tool tips displaying and forcing the background window to the top. This was resolved by a call to initOwner(), I assume setting a proper window hierarchy.
  • getInstance() is usually only used for message passing between parent/child windows
  • Why make myStage static? Sometimes I find it useful to add a method that allows parent/child windows to have direct access to certain controls (like status message labels, or progress bars). Other times I need access to the stage in a stop() method.

There are of course, multiple ways to accomplish the stated goals. This is just my (current) way.

Comments welcome…

This entry was posted in JavaFX. Bookmark the permalink.

3 Responses to JavaFX from the Trenches – Singleton Controllers

  1. Mircea says:

    Nice info.

  2. Pingback: JavaFX links of the week, January 7 // JavaFX News, Demos and Insight // FX Experience

  3. Pingback: Java desktop links of the week, January 7 | Jonathan Giles

Leave a Reply

Your email address will not be published. Required fields are marked *