JavaFX8 FXML 控制器注入

JavaFX8 FXML Controller injection

在我的 GUI 应用程序中,我有两个视图:playlistView.fxmlvideoView.fxml。每个都有自己的控制器。我希望 playListView 成为 videoView 布局的一部分,所以我使用:

<fx:include fx:id="idPlayListAnchorPane" source="playListView.fxml" />

包含文件。工作正常,播放列表显示为 videoView 布局的一部分。

然后我将 idPlayListAnchorPane FXML 变量注入到 VideoViewController 中,如下所示:

@FXML
private AnchorPane idPlayListAnchorPane;    

也可以。例如,我可以从 VideoViewController 中禁用 playListView 中的 idPlayListAnchorPane

idPlayListAnchorPane.setDisable(true);

要获取我使用的 playListViewController:

FXMLLoader loader = new FXMLLoader(Main.class.getResource("/designer/views/video/playListView.fxml"));
    PlayListViewController playListViewController = new PlayListViewController();
    loader.setController(playListViewController);
    try {
        AnchorPane playListView = (AnchorPane) loader.load();
    } catch (IOException e) {
    };

然后我可以调用例如:

playListViewController.init();    

来自 videoView控制器

但是 init() 方法在 playListView ListView 中创建了一些测试值(作为单独的应用程序测试并且有效)。但是,这些测试值现在不会显示在 ListView 中。许多小时后的简单问题是:为什么不呢?

您正在加载 playListView.fxml 文件两次:一次从 <fx:include> 加载,一次是在代码中创建 FXMLLoader 并调用 load()。由 <fx:include> 创建的节点层次结构(即 AnchorPane 及其所有内容)显示在您的 GUI 中; FXMLLoader.load() 调用创建的不是。

由于您创建的控制器与未显示的节点层次结构相关联,因此您在控制器上调用的方法将不会影响您的 UI。

无需创建 FXMLLoader 来获取控制器实例,您可以使用文档中描述的 Nested Controller 技术将包含的 FXML 中的控制器直接注入到您的 VideoViewController 中。

为此,首先将 fx:controller 属性添加到 playListView.fxml 根元素:

playListView.fxml:

<!-- imports etc -->
<AnchorPane fx:controller="com.mycompany.packagename.PlayListViewController">
    <!-- etc etc -->
</AnchorPane>

因为您在 <fx:include ...> 上定义了 fx:id="idPlayListAnchorPane" 属性,您可以使用 @FXML 将控制器直接注入 VideoViewController class - 名为 idPlayListAnchorPaneController 的注释字段(规则是将 "Controller" 附加到 id):

public class VideoViewController {
    @FXML
    private AnchorPane idPlayListAnchorPane;
    @FXML
    private PlayListViewController idPlayListAnchorPaneController ;

    // ...
}

现在您可以根据需要调用控制器上的方法。