Search code examples
javajavafxstagejavafx-11

How to access the stage in another class?


I use FXMLLOADER to load a fxml file SignInUI.fxml in LogUIController. The code is here:

Stage signIn = new Stage();
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("SignInUI.fxml"));
SignInUIController signInUIController = new SignInUIController();
signInUIController.setStage(signIn);
Scene sceneSignIn = new Scene(fxmlLoader.load());
signIn.setTitle("Sign In");
Image icon = new Image("calculator.jpg");
signIn.getIcons().add(icon);
signIn.setScene(sceneSignIn);
signIn.show();

I wrote a method called setStage in SignInUIController, which can assign the instance variable stage:

public Stage stage;

public void setStage(Stage stage) {
    this.stage = stage;
}

I tried to build a SignInUIController instance in LogUIController and call the setStage method. Lastly, the cancel method in SignInUIController tied to a button and use the instance variable stage to close the stage:

@FXML
private void cancel() throws IOException {
    stage.close();
}

But every time, it has an error:Cannot invoke "javafx.stage.Stage.close()" because "this.stage" is null. I do not know why, and how to fix this?


Solution

  • There's probably a better way of doing this, but here's a quick, alternative fix.

    Try instantiating your controller using the .getController() class of the FXMLLoader object. Also you can try getting the Window of the scene you have created and cast that to a stage. I made sure to call the setStage method only after setting the scene so that the Scene's Window isn't null.

    Stage signIn = new Stage();
    FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("SignInUI.fxml"));
    SignInUIController signInUIController = fxmlLoader.getController();
    Scene sceneSignIn = new Scene(fxmlLoader.load());
    signIn.setTitle("Sign In");
    Image icon = new Image("calculator.jpg");
    signIn.getIcons().add(icon);
    signIn.setScene(sceneSignIn);
    signInUIController.setStage(sceneSignIn.getWindow());
    signIn.show();
    

    And then in the setStage function of your controller, try setting the parameter to Window instead of Stage:

    public void setStage(Window _window){
        // set the stage variable in your class to the casted window
        this.primaryStage = (Stage) _window; 
    }