Accessing the parent class of JavaFX accessor class from FXML child

using JavaFX for an application and I have a Main.fxml file with some fxml child files inside it.

I would like to access the MainController class Main.fxml from the child controllers.

I'll try to explain better with an example:

MainFxml:

    <HBox fx:controller="MainController.java">
        <fx:include source="child.fxml"/>
    </HBox>

      

MainController:

    public class MainController implements Initializable {
            private String string;
            public void setString (String string) {
                    this.string = string;
            }

      

ChildFxml:

    <HBox fx:id="child" fx:controller="ChildController.java">
        <Button text="hello" onAction="#selectButton"></Button>
    </HBox>

      

ChildController:

    public class ChildController implements Initializable {
            @FXML HBox child;
            @FXML Button button;
            @FXML
            public void selectButton (ActionEvent event) {
                // here call MainController.setString("hello");
            }

      

I tried this StackOverflow question but I need to get the Controller link for Main.fxml which is already loaded. Is there a way to get the controller starting from a specific panel? Something like:

    // child.getParent().getController();

      

+3


source to share


2 answers


If you are assigning a tag to a fx:id

tag <fx:include>

, it FXMLLoader

tries to inject the controller of the included fxml into the name field <fx:id>Controller

. You can pass a reference MainController

to child controllers in the method initialize

:

<HBox fx:controller="MainController.java">
    <fx:include fx:id="child" source="child.fxml"/>
</HBox>

      

MainController

@FXML
private ChildController childController;

@Override
public void initialize(URL url, ResourceBundle rb) {
    childController.setParentController(this);
}

      

ChildController

private MainController parentController;

public void setParentController(MainController parentController) {
    this.parentController = parentController;
}

@FXML
private void selectButton (ActionEvent event) {
    this.parentController.setString("hello");
}

      




However, it would be better to keep it ChildController

independent from the parent. This can be done by providing StringProperty

in ChildController

, which receives the value that the parent should show.

ChildController

private final StringProperty value = new SimpleStringProperty();

public StringProperty valueProperty() {
    return value;
}

@FXML
private void selectButton (ActionEvent event) {
    value.set("hello");
}

      

ParentController

@Override
public void initialize(URL url, ResourceBundle rb) {
    childController.valueProperty().addListener((observable, oldValue, newValue) -> setString(newValue));
}

      

+4


source


I have solved this problem in my projects using model Singleton

. You can use a separate class to store references to parent controllers.

For example:

Global.java:

public class Global {

    public static ParentControllerClass parentController;

    private Global() {
    }

    public static ParentControllerClass getParentController() {
        return mainApp;
    }

    public static void setParentController(ParentControllerClass parentController) {
        Global.parentController = parentController;
    }
}

      



Inside the parent controller, you just need to pass a reference to yourself to the class Global

by calling Global.setParentController(this);

. Then you can access it from the child using Getter:Global.getParentController();

This is preferred if the parent and child share the same controller, as it helps clean up your code and makes it easier to read.

I'm new to Java myself and it may not be the most difficult method to use in this scenario, but it has worked fine for me so far.

0


source







All Articles