如何在另一个类中访问Stage?FXML加载后Stage为空问题解决
问题分析与修复:Stage对象为空的原因及解决方法
问题根源
你手动创建的SignInUIController实例,和FXMLLoader加载FXML时自动生成的控制器实例不是同一个对象。你给手动创建的实例设置了stage,但FXML实际绑定的是Loader创建的未赋值stage的实例,因此调用stage.close()时会触发空指针异常。
修复方案
方案1:让FXMLLoader使用你创建的控制器实例
修改LogUIController中的加载代码,将你创建的控制器实例绑定到FXMLLoader,确保Loader加载FXML时复用这个已赋值stage的实例:
Stage signIn = new Stage(); FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("SignInUI.fxml")); // 创建控制器实例并设置stage SignInUIController signInUIController = new SignInUIController(); signInUIController.setStage(signIn); // 将控制器绑定到FXMLLoader fxmlLoader.setController(signInUIController); // 加载FXML并创建场景 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();
注意:使用该方案时,需要删除FXML文件根元素的
fx:controller属性,否则FXMLLoader会尝试自动创建控制器,导致冲突报错。
方案2:加载FXML后获取控制器实例并设置stage
无需手动创建控制器,而是在FXMLLoader加载完成后,获取它自动生成的控制器实例,再为其设置stage:
Stage signIn = new Stage(); FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("SignInUI.fxml")); // 先加载FXML Scene sceneSignIn = new Scene(fxmlLoader.load()); // 获取Loader创建的控制器实例 SignInUIController signInUIController = fxmlLoader.getController(); // 为该实例设置stage signInUIController.setStage(signIn); signIn.setTitle("Sign In"); Image icon = new Image("calculator.jpg"); signIn.getIcons().add(icon); signIn.setScene(sceneSignIn); signIn.show();
该方案可以保留FXML文件中的fx:controller属性,符合JavaFX常规开发流程。
方案3:无需传递Stage,通过控件直接获取
在SignInUIController的cancel方法中,通过任意已绑定的FXML控件获取所在窗口的Stage,避免维护额外的实例变量:
@FXML private Button cancelBtn; // 假设cancel按钮已在FXML中绑定该变量 @FXML private void cancel() throws IOException { // 通过控件获取所在的Stage Stage stage = (Stage) cancelBtn.getScene().getWindow(); stage.close(); }
这种方式无需在外部传递Stage,从根源上避免空指针问题。
内容的提问来源于stack exchange,提问作者Cao Dingjie
相关产品推荐
相关产品推荐

