JavaFX - getScene() returns null
Asked Answered
D

3

19

I just started using JavaFX Scene Builder to build a small application.

It is made up of a controller class 'Login.java' which belongs to 'login.fxml', in which the FXML file 'registrierung.fxml' is loaded via a method called 'registrationClicked(ActionEvent event)':

public class Login {

@FXML
private void registrationClicked(ActionEvent event){
    try{
        ((Node) (event.getSource())).getScene().getWindow().hide();
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/fxml/registrierung.fxml"));
        Parent root = (Parent) loader.load();
        Stage stage = new Stage();
        Scene scene = new Scene(root);      
        stage.setTitle("Registration");
        stage.setScene(scene);
        stage.setResizable(false);
        stage.show();
    } catch(IOException e){
        e.printStackTrace();
    }
}

Now I want to get a reference to the stage of 'registrierung.fxml' in the controller class 'Registrierung.java' via the root node vboxRoot:

@FXML
private VBox vboxRoot;

Stage stage = (Stage) vboxRoot.getScene().getWindow();

However 'getScene()' always leads to a NullPointerException. The controller classes for both FXML files are adjusted in Scene Builder.

This is how I set up the rood node in 'registrierung.fxml':

<VBox fx:id="vboxRoot" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="267.0" prefWidth="355.0" stylesheets="@../css/styles.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="businesslogik.Registrierung">

What am I doing wrong?

Dynamometry answered 26/5, 2015 at 16:36 Comment(5)
Is your vboxRoot initialized?Hulen
I just quoted the way I set up the root node in the fxml file and in the controller class. Please take a look.Dynamometry
Where is that code? In an event handler?Excitant
At the moment it's a field in the 'Registrierung.java' controller class. I'm new to JavaFX, but for me it seems to be in the right position.Dynamometry
Since vboxRoot is injected by the FXMLLoader, it cannot possibly be initialized until after the controller is created. Hence it is null here. Moreover, the root of the FXML is not placed in a Scene (or, consequently, a Stage) until after the FXMLLoader's load method is completed (just look at the order of your code in registrationClicked(...)). So you cannot possibly access theScene or the Stage until after the load process (including the initalize() method) is complete. Access the window only when you need it, which is likely in an event handler.Excitant
A
11

you are trying to get the scene for an object that has not been initialized yet. if you were doing the same operation in

@Override 
    public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
    Stage stage = (Stage) vboxRoot.getScene().getWindow();
}

or if you have an event that triggers once you click something (which executes after the scene has loaded)

@FXML
private void action(ActionEvent event) throws IOException {
    Stage stage = (Stage) vboxRoot.getScene().getWindow();
}

This would work!

Atom answered 7/7, 2015 at 19:59 Comment(0)
S
9

I have run into this issue and have found by placing a call to a method like this (When the scene becomes visible and is attached to the node, this will fire):

 private void determinePrimaryStage() {
        rootPane.sceneProperty().addListener((observableScene, oldScene, newScene) -> {             
            if (oldScene == null && newScene != null) {
                // scene is set for the first time. Now its the time to listen stage changes.
                newScene.windowProperty().addListener((observableWindow, oldWindow, newWindow) -> {
                    if (oldWindow == null && newWindow != null) {
                        primaryStage = (Stage)newWindow;
                    }
                });
            }
        });
    }`

Then I can do something like this later:

if(primaryStage == null) {
    Platform.runLater(()-.{......
}else {
   //do whatever
}

Hope this helps.

Styria answered 7/7, 2015 at 20:7 Comment(0)
M
2

Implementing the Initializable interface did not work for me(Java 8). The method getScene() always returned null for me. So i had to do the following:

FXMLLoader loader = new FXMLLoader(getClass().getResource("MyGui.fxml"));
Parent root = (Parent)loader.load();
//do stage and scene stuff - i skip it here
MyController controller = (MyController)loader.getController();
stage.setOnShown(controller::adjustUI);

And in the controller i have:

public void adjustUI(WindowEvent event) {
    Scene scene = myComponent.getScene();
    //do stuff and do ui adjustments here
}
Minded answered 22/3, 2019 at 0:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.