I want to create a desktop application that changes scenes depending on menu choice.
I believe that the norm is to have a single controller for each FXML scene. But. how to I manage moving from one scene to the next? Is the Main class the location that handles all the scenes and switches between them? Any examples or links to sites with this type of information would be greatly appreciated.
I usually do it like this:
- A main FXML with just a BorderPane (or any layout container) and MenuBar. The layout has its own Controller class (say "MainScreenController") responsible for handling menu item clicks.
- This main FXML is loaded as root node of primary Scene, and this scene is set into primaryStage. The stage's scene is never changed.
- Any UI screen is modelled as a standalone FXML (with its own Controller class). FXML gets loaded, and its root node is then added as a child node to the main FXML's BorderPane (or other layout container).
At a high level, this is how I compose views.
But I don't do that loading of UI screen FXMLs directly in the menu item event handler. That's not good design, because there may be other actions initiated outside of menu bar which may also require the exact same response. If I code all that response logic inside one layout controller's event handler, it's impossible to reuse cleanly without all kinds of reference passing hacks, resulting in a sphagetti object graph.
Instead, I do it like this:
- I have an application level controller class that is responsible for initiating the entire flow for every application use case.
- On menu item click, layout controller calls application level controller's appropriate use case method. Taking your example, it would look something like this:
- It's this applicationController that then collaborates with multiple layout controllers (including MainScreenController) and models to execute the use case.
This centralization is necessary because a use case initiated from one layout may require responses - like disabling some controls or showing a busy icon - in other layouts.
Also, every root node of a FXML layout can have its own Controller instance. It's not necessarily one Scene - one Controller. A Scene's scene graph may be composed using a tree of FXML files, each of which can have its own controller.