在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();
}
答案 0 :(得分:4)
您需要获取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的控制器类的占位符(你没有提到过)。如果您还没有像以下那样在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上调用一个方法,并使用getter和setter添加此Controller。
3)ResourceBundle用于提及名称,主要用于国际化您的应用程序。