遵循http://www.javafxtutorials.com/tutorials/switching-to-different-screens-in-javafx-and-fxml/上的教程之后,我有一个正常运行的弹出窗口,但是,我很难弄清楚如何与控制器进行交互。
从教程中,我得到了两个FXML文件之间存在共享控制器的印象,但是我在引用新阶段时遇到了麻烦。
对此,我有几个问题。
@FXML
private void toOutput(ActionEvent event) throws Exception {
Stage stage;
Parent root;
stage = new Stage();
root = FXMLLoader.load(getClass().getResource("TextWindow.fxml"));
stage.setScene(new Scene(root));
stage.initModality(Modality.APPLICATION_MODAL);
stage.initOwner(searchBox.getScene().getWindow());
stage.showAndWait();
}
1)运行上面的命令时,stage.showAndWait()是否使用新的控制器创建新的场景实例,还是在现有的场景控制器上工作?
2a)如果使用新的控制器,这是否有益?我猜想控制器会通过其他包装来构建东西,因此它可能只会从@FXML标记中提取所需的东西,但是我有局部变量,等等似乎不是一个好主意。
2b)如果使用现有的控制器,如何引用类实例的局部变量?它可能非常简单,但是FXML总体上对我来说还是很陌生。
3)如果要使用完全独立的控制器(假设我无法使它与单个控制器一起使用),如何将数据元素从一个控制器传递到另一个控制器?我看到initialize()方法有一个ResourceBundle的参数,但是我不确定如何利用它。
答案编辑
正确的代码:
@FXML
private void toOutput(ActionEvent event) throws Exception {
Stage stage = new Stage();
Parent root;
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("OutputWindow.fxml"));
root = loader.load();
OutputWindowController controller = loader.getController();
controller.setMat(mat);
stage.setScene(new Scene(root));
stage.initModality(Modality.APPLICATION_MODAL);
stage.initOwner(searchBox.getScene().getWindow());
stage.showAndWait();
}
最佳答案
您需要获取由fxml设置(如果有)的(新)控制器。
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("TextWindow.fxml"));
root = loader.load();
Controller controller = loader.getController(); // type need to be put here
controller.setCallingController(this); // this could be any method you need
请不要尝试使用已经由另一个fxml赋予其他任何fxml的一个控制器,这不是正确的方法。
因此,您只需要从加载程序中获取控制器即可。上面代码中的Controller只是您已设置为fxml(未提及)的Controller类的占位符。如果尚未在fxml中设置控制器,如下所示:
fx:controller="package.to.your.Controller"
请在那里设置。在加载器上调用load()方法是一种通用方法(感谢James_D),因此它返回fxml用作root的组件的类型。
您的问题的答案:
1)Stage就像Window或Swing中的JFrame一样,因此将使用新的Controller(如果已设置)创建一个新Stage。
2a)每个fxml需要一个自己的控制器(由于资源注入)。它与对象身份有关。在您提到的教程中,它有点隐藏,但是在每次调用FXMLLoader.load(fxml-file)时,都会创建FXMLDocumentController类的新控制器实例。而且如果这还不够糟糕,则由于资源注入,按钮之一始终指向null。现在想想一个巨大的应用程序,面板上有多个按钮!您将多久执行一次if-else语句来知道按下了哪个按钮?从我的角度来看,这是一种错误的模式,它是摆动代码的“老式样式”。不要使用它。
2b)不要使用现有的Controller,它将失败。只需在新Controller上调用一个方法,然后将此控制器添加到getter和setter中即可。
3)ResourceBundle用于提及名称,主要用于国际化您的应用程序。