1
votes

I created JavaFX application and want to distribute complete functionality among different FXML with hierarchy and MVC structure.

At the start time RoolLayout.fxml is load which is parent FXML

RootLayout.fxml

<BorderPane prefHeight="400.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.nikunj.drclinic.controller.RootLayoutController">
<center>
  <AnchorPane fx:id="dashboard" BorderPane.alignment="CENTER" />
</center>
<top>
  <HBox BorderPane.alignment="CENTER">
     <children>
        <fx:include fx:id="mainMenu" source="MainMenuBar.fxml" />
     </children>
  </HBox>
</top>
</BorderPane>

For this used controller is RootLayoutController.java

public class RootLayoutController {

 @FXML
 private MainMenuBarController mainMenuBarController;

 @FXML
 private AnchorPane dashboard;

 @FXML
 private void initialize() {
    // Initialize the person table with the two columns.
 }
}

From inside this MainMenuBar.fxml file is also loaded which is child fxml file

MainMenuBar.fxml

<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.nikunj.drclinic.controller.MainMenuBarController">
   <children>
      <MenuBar layoutY="2.0" prefWidth="1000.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <menus>
          <Menu mnemonicParsing="false" text="File">
            <items>
              <MenuItem mnemonicParsing="false" onAction="#closeApplication" text="Close" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Patient Detail">
            <items>
              <MenuItem fx:id="addPatiendMenuItem" mnemonicParsing="false" onAction="#addPatient" text="Add Patient" />
                  <MenuItem mnemonicParsing="false" text="Find Patient" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
   </children>
</AnchorPane>

controller file for this MainMenuBar.fxml is MainMenuBarController.java

public class MainMenuBarController {

 @FXML
 private MenuItem addPatiendMenuItem;

 @FXML
 private MenuItem findPatientMenuItem;

 @FXML
 public void closeApplication(){
    System.exit(0);
 }

 @FXML
 public void addPatient(ActionEvent event){

 }
}

Now on selection of menu item addPatiendMenuItem from controller addPatient(ActionEvent event) method is called. From this method how can i change the AnchorPane fx:id = "dashboard" which is component of the parent fxml (RootLayout.fxml) file.

Suppose i want to load content of third fxml (i.e. Dashboard.fxml) in this AnchorPane, how can i do that?

I spend lots of hours to find, how to change parent controller component from the action performed on child controller component?

1

1 Answers

1
votes

Create a property in the MainMenuBarController that represents the state you are changing ("view state"). Making this make sense depends on knowing a bit more about your application, but you might do something like

public class MainMenuBarController {
    private final BooleanProperty addPatientRequested = new SimpleBooleanProperty();
    public BooleanProperty addPatientRequestedProperty() {
        return addPatientRequested ;
    }
    public final boolean isAddPatientRequested() {
        return addPatientRequestedProperty().get();
    }
    public final boolean setAddPatientReqested(boolean requested) {
        addPatientReqestedProperty().set(requested);
    }

    @FMXL
    private void addPatient(ActionEvent event) {
        setAddPatientRequested(true);
    }
}

Then in the "parent" controller do

public class RootLayoutController {

 @FXML
 private MainMenuBarController mainMenuBarController;

 @FXML
 private AnchorPane dashboard;

 @FXML
 private void initialize() {
    // Initialize the person table with the two columns.
    mainMenuBarController.addPatientRequestedProperty().addListener((obs, wasRequested, isNowRequested) -> {
        if (isNowRequested) {
            // code to execute...
        }
    });
 }
}

Depending on your application logic, you might want a different property, e.g. in the MainMenuBarController define

ObjectProperty<Node> display = new SimpleObjectProperty<>();

which would store the node the RootLayoutController is supposed to display. The structure would be similar, set that property in the addPatient handler method and listen to it in the RootLayoutController