如何在另一个类中访问舞台?

3
我在LogUIController中使用FXMLLOADER来加载一个名为SignInUI.fxml的fxml文件。代码如下:
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();

我在SignInUIController中编写了一个名为setStage的方法,它可以给实例变量stage赋值。
public Stage stage;

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

我试图在LogUIController中构建一个SignInUIController实例,并调用setStage方法。最后,将SignInUIController中的cancel方法与一个按钮绑定,并使用实例变量stage关闭舞台。
@FXML
private void cancel() throws IOException {
    stage.close();
}

但每次都会出现一个错误:Cannot invoke "javafx.stage.Stage.close()" because "this.stage" is null。我不知道为什么,也不知道如何解决这个问题?

首先,如果cancel是一个ButtononAction方法,它应该是private void cancel(ActionEvent actionEvent)。其次,我猜你可能在寻找以下内容。https://dev59.com/tl8f5IYBdhLWcg3wFvan#41838183 - SedJ601
2个回答

3
你没有在运行阶段绑定控制器,因此你放置的父级舞台实例与实际渲染的窗口不是关联的。 如果你想以编程方式设置它,请查看这个答案
示例:
  FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("SignInUI.fxml"));
  fxmlLoader.setController(new SignInUIController());

我在fxml文件中绑定了控制器。但是我通过创建一个新的实例变量来修复了这个问题,该变量是anchorPane,并使用以下代码:stage = (Stage) anchorPane.getScene().getWindow(); 现在我只想知道为什么我的之前尝试总是返回一个空的stage。 - Cao Dingjie
1
在你的第3行,你正在创建一个新的SignInUIController实例。该实例不受Java FX应用程序控制,所以父舞台的状态始终为null。如果你想要重用相同的实例,请查看此链接:link - AntJavaDev
@CaoDingjie,你做事情都错了。我首先注意到的是你从来没有使用fxmlLoader.load,也从来没有使用fxmlLoader.getController。请参考https://dev59.com/MFwY5IYBdhLWcg3wq5bk。 - SedJ601
@SedJ601 Cao在他的问题中确实调用了Scene sceneSignIn = new Scene(fxmlLoader.load());。Cao可以按照你的建议,在加载后从加载器中获取控制器,进行一些重构。或者Cao可以像AntJavaDev的答案中所示,将控制器设置为与Passing Parameters JavaFX FXML中的设置控制器部分类似,但也请注意那里的评论中提到的“要在加载器上设置控制器(在JavaFX 2.x中),您不能在fxml文件中定义fx:controller属性。”不确定是否适用于最新的JavaFX。 - jewelsea
@jewelsea,谢谢提供信息。我也错过了Scene sceneSignIn = new Scene(fxmlLoader.load());这一部分。 - SedJ601

2
可能有更好的方法来解决这个问题,但这里是一个快速的替代修复方案。
尝试使用FXMLLoader对象的.getController()类来实例化您的控制器。另外,您可以尝试获取您创建的场景的窗口,并将其转换为舞台。我确保在设置场景之后才调用setStage方法,以确保场景的窗口不为空。
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();

在您的控制器的setStage函数中,尝试将参数设置为Window而不是Stage。
public void setStage(Window _window){
    // set the stage variable in your class to the casted window
    this.primaryStage = (Stage) _window; 
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接