-1

Edit: I believe I found the correct answer to my problem after all.

Original Post:

I'm currently trying to create an application with JavaFX and an EventBus-System. To do this, I have to pass the EventBus as constructor argument to other classes when instantiating them. However I don't know how to do this while also using an FXMLLoader to load my .fxml-Files.

My code currently looks somethinng like this:

Main Class

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

}

This class inherits from BorderPane and I want to create an object of it using fxmlLoader (I think. I'm not sure if it works like that)

puplic class MainView extends BorderPane {

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

}

I also have a controller for MainView (don't know if thats important to mention)

public class MainViewController {
    >>> several JavaFX Elements like buttons, labels etc and their associated functionalities like onActions and such... <<<<
}

And of course there is an .fxml-File that contains the actual design of the MainView that I created with SceneBuilder, but I won't post it here since it doesn't seem necessary. But I sould probably mention that this .fxml-File contains a BorderPane as it's highest node. I think that makes sense, since my MainView extends BorderPane.

My Problem is that I ever created my own class that extends BorderPane and needs a Constructor parameter before and I don't really know how to create an instance of it.

In the past I did something like this:

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

I of course looked for solutions online but those posts talk about passing arguments between windows and such.

Thanks in advance for your help.

Wewius
  • 87
  • 7
  • [mcve] please .. and stick to java naming conventions – kleopatra Jan 27 '23 at 12:52
  • 1
    _those posts talk about passing arguments between windows and such_ no, they are talking about passing parameters between collaborators (the strategy is the same, no matter of which type ;), see the javafx tag wiki ("learn more" link on the fx question overview page) for related QAs. Take one, apply what you learned from it, when stuck come back with a concrete problem. – kleopatra Jan 27 '23 at 12:55
  • Thank you. What did I do wrong with the naming conventions? – Wewius Jan 27 '23 at 13:04
  • you fixed the naming violation, why do you ask ;) – kleopatra Jan 27 '23 at 13:46
  • I found it after I wrote the comment. ^^* – Wewius Jan 27 '23 at 14:23

1 Answers1

4

You can use a dynamic root in the FXML.

Briefly, the FXML will look like:

<fx:root 
    type="javafx.scene.layout.BorderPane"
    xmlns:fx="http://javafx.com/fxml"
    fx:controller="com.mycompany.myproject.MainViewController">
    <!-- Controls etc. -->
</fx:root>

And then in the MainView constructor do

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

}

The controller will just behave the same as the controller in an FXML with a static root. That is, you could communicate with the controller if needed with:

    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...
    }

or if you needed to instantiate it by hand, omit the fx:controller attribute from the FXML file, and then do

    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();
    }
James_D
  • 201,275
  • 16
  • 291
  • 322