遵循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用于提及名称,主要用于国际化您的应用程序。

08-04 00:29
查看更多