JavaFX:使用 FXMLLoader 将参数传递给自己的类

Wew*_*ius -1 javafx fxml fxmlloader

编辑:我相信我终于找到了问题的正确答案。

原帖:

我目前正在尝试使用 JavaFX 和 EventBus 系统创建一个应用程序。为此,我必须在实例化其他类时将 EventBus 作为构造函数参数传递给它们。但是我不知道如何在使用 FXMLLoader 加载我的 .fxml 文件的同时执行此操作。

我的代码目前看起来像这样:

主班

public class MyApplication extends Application {

    public void start(Stage stage) throws Exception {
        EventBus eventBus = new EventBus();

       >>> Here would be code that creates an Object of MainView, passing eventBus as constructor argument. <<<

        Scene scene = new Scene(mainView);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}
Run Code Online (Sandbox Code Playgroud)

这个类继承自 BorderPane,我想使用 fxmlLoader 创建它的对象(我想。我不确定它是否像那样工作)

puplic class MainView extends BorderPane {

    private EventBus eventBus;
    
    public MainView(EventBus eventBus) {
        this.eventBus = eventBus;
        ... other code
    }

}
Run Code Online (Sandbox Code Playgroud)

我还有一个 MainView 控制器(不知道这是否重要)

public class MainViewController {
    >>> several JavaFX Elements like buttons, labels etc and their associated functionalities like onActions and such... <<<<
}
Run Code Online (Sandbox Code Playgroud)

当然,还有一个 .fxml 文件,其中包含我使用 SceneBuilder 创建的 MainView 的实际设计,但我不会将其发布在这里,因为它似乎没有必要。但我可能会提到这个 .fxml 文件包含一个 BorderPane 作为它的最高节点。我认为这是有道理的,因为我的 MainView 扩展了 BorderPane。

我的问题是,我曾经创建过自己的类,它扩展了 BorderPane 并需要一个构造函数参数,但我真的不知道如何创建它的实例。

过去我做了这样的事情:

        FXMLLoader loader = new FXMLLoader();
        BorderPane root = loader.load(getClass().getResourceAsStream("MainView.fxml"));
        
        Scene scene = new Scene(root);
        stage.show();
Run Code Online (Sandbox Code Playgroud)

我当然在网上寻找解决方案,但这些帖子讨论了在窗口之间传递参数等。

在此先感谢您的帮助。

Jam*_*s_D 5

您可以在 FXML 中使用动态根。

简而言之,FXML 将如下所示:

<fx:root 
    type="javafx.scene.layout.BorderPane"
    xmlns:fx="http://javafx.com/fxml"
    fx:controller="com.mycompany.myproject.MainViewController">
    <!-- Controls etc. -->
</fx:root>
Run Code Online (Sandbox Code Playgroud)

然后在MainView构造函数中做

public class MainView extends BorderPane {

    private EventBus eventBus;
    
    public MainView(EventBus eventBus) {
        this.eventBus = eventBus;
        FXMLLoader loader = new FXMLLoader(getClass().getResourceAsStream("MainView.fxml"));
        loader.setRoot(this);
        loader.load();
    }

}
Run Code Online (Sandbox Code Playgroud)

该控制器的行为与具有静态根的 FXML 中的控制器相同。也就是说,如果需要,您可以通过以下方式与控制器通信:

    public MainView(EventBus eventBus) {
        this.eventBus = eventBus;
        FXMLLoader loader = new FXMLLoader(getClass().getResourceAsStream("MainView.fxml"));
        loader.setRoot(this);
        loader.load();
        MainViewController controller = loader.getController();
        // etc...
    }
Run Code Online (Sandbox Code Playgroud)

或者,如果您需要手动实例化它,请省略fx:controllerFXML 文件中的属性,然后执行

    public MainView(EventBus eventBus) {
        this.eventBus = eventBus;
        MainViewController controller = new MainViewController(...);
        FXMLLoader loader = new FXMLLoader(getClass().getResourceAsStream("MainView.fxml"));
        loader.setRoot(this);
        loader.setController(controller);
        loader.load();
    }
Run Code Online (Sandbox Code Playgroud)