JavaFX8:1 + 1popup场景的单个控制器

时间:2015-06-16 20:36:31

标签: java javafx fxml

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();

}

1 个答案:

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