Entry Level Scene Switching with JavaFX
Inside our JavaFX application, we’re usually not going to want to rely only on one scene to handle, so the problem will arise on how we switch to another scene and all of the flow of our application data to that scene. The most logical way I’ve found to accomplish this is by just swapping out the root scene wherever we currently reside in the application. There are two ways we’ll want to do this; a clean scene that needs no data sent across and in a situation where we’ll need to initialize some data for the loading scene.
🧼Loading a scene without data initialization
Here we’ll work out how to load a scene that does not require any data to be sent across. This route will be straightforward, similar to how we initially bootstrap our application.
Let’s create a little checklist to take a look at what we need to do:
- load the new scenes fxml
- assign the new fxml file to a scene
- get the application root stage
- load the new scene into the stage
- show the updated stage
A lot of this will look similar to initial bootstrapping in your main entry point, so that I will fly through this. We start by creating a Parent that will load our target views fxml file. From here, we create a Scene by passing along the Parent we made.
- load the new scenes fxml
- assign the new fxml file to a scene
This is where we diverge from basic loading; we need the Stage defined in the initial loading of the application; we can gain access to this from the ActionEvent that we will be passing down from the current scene we are attempting to leave. On the event passed down, we can grab the source of the event as a Node, and from here drill down by next grabbing the Scene associated with it, and finally, the Window that the scene was loaded in (we will need to cast this to a Stage ).
- get the application root stage
Once we have acquired the window, we can set its scene to our target and launch it by calling .show().
- load the new scene into the stage
- show the updated stage
public static void loadScene(ActionEvent event, String fxmlFileName) throws IOException {
Parent viewParent = FXMLLoader.load(getClass().getResource(fxmlFileName));
Scene viewScene = new Scene(viewParent);
Stage window = (Stage) ((Node) event.getSource()).getScene().getWindow();
window.setScene(viewScene);
window.show();
} 🧱Loading a scene with data initialization
Loading a scene that requires some data initialization is similar to our previous example of loading a scene without data; there are just a couple of extra steps we’ll need to sneak in that will allow us to call methods from that target scene controller before showing the window. Our checklist for this example will only add one extra step, but the code will have a few changes.
- load the new scenes fxml
- assign the new fxml file to a scene
- call data initialization method in target scene controller
- get the application root stage
- load the new scene into the stage
- show the updated stage
After assigning our target FXML file to a Scene, we will need to gain access to the target controller by using a method on FXMLLoader called getController() . At this point, we now have access to the controller and can call a method that handles the passed data; we’ll call it ‘initData’.
- call data initialization method in target scene controller
public static void loadScene(ActionEvent event, String fxmlFileName, Person personOne)
throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource(fxmlFileName));
Parent viewParent = loader.load();
Scene viewScene = new Scene(viewParent);
SecondController c = loader.getController();
c.initData(personOne);
Stage window = (Stage) ((Node) event.getSource()).getScene().getWindow();
window.setScene(viewScene);
window.show();
} 🎩 Tada
And there, we have two primary examples of how you can load new scenes in your JavaFX applications. The first shows you how to load a new Scene without sending any data, and the second covers a basic example of sending data to your new Scene to be initialized in its controller.