To make what you want, you need to have access to the controllers (the controllers themselves must be able to communicate with each other). FXMLLoader
offers several options for accessing controllers. The first option is to automatically inject the fxml components included with the include
in the fxml file.
<fx:include fx:id="childView" source="child.fxml"/>
In order for the controller to be injected, a field of the controller type specified in child.fxml
must be declared with the name specified in fx:id
with suffix Controller. And of course, annotate with @FXML
.
public class MainController {
@FXML
private ChildController childViewController;
...
}
If you are going to be working with a dynamically changing context, you can manually create the controller and pass it on to FXMLLoader
, which will initialize it by injecting the appropriate fields or simply picking up the initialized instance.
Here, it's important to first call FXMLLoader#load()
, and then FXMLLoader#getController()
.
FXMLLoader loader = new FXMLLoader(getClass().getResource("/resource/layout/child.fxml"));
Parent parent = loader.load();
ChildController controller = loader.getController();
When manually creating the controller, you must first call FXMLLoader#setController()
and then FXMLLoader#load()
.
ChildController controller = new ChildController();
FXMLLoader loader = new FXMLLoader(getClass().getResource("/resource/layout/child.fxml"));
loader.setController(controller);
Parent parent = loader.load();
Consequently, communication between controllers is trivial and I do not think there is a need to explain.
UPDATE
An example of how communication is made between objects.
These are the two views that use the app:
child.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<HBox alignment="CENTER_LEFT" spacing="5.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.ChildController">
<children>
<Label text="Child View" />
<TextField fx:id="textField" HBox.hgrow="ALWAYS" />
<Button mnemonicParsing="false" text="Send to parent" onAction="#handleSendButton"/>
</children>
</HBox>
sample.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" spacing="5.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.MainController">
<children>
<HBox spacing="5.0">
<children>
<TextField fx:id="textField" editable="false" HBox.hgrow="ALWAYS" />
<Button mnemonicParsing="false" text="Refresh" onAction="#handleRefreshButton"/>
</children>
</HBox>
<HBox fx:id="childContainer">
<fx:include fx:id="childView" source="child.fxml" />
</HBox>
</children>
</VBox>
And respectively the two controllers.
public class ChildController {
@FXML
private TextField textField;
private Consumer<String> consumer;
public void addConsumer(Consumer<String> consumer) {
this.consumer = consumer;
}
@FXML
private void handleSendButton(ActionEvent event) {
if(consumer == null) {
return;
}
consumer.accept(textField.getText());
}
}
Here, pressing the Refresh button reloads the inserted view.
public class MainController {
@FXML
private TextField textField;
@FXML
private HBox childContainer;
@FXML
private ChildController childViewController;
@FXML
private void initialize() {
childViewController.addConsumer(textField::setText);
}
@FXML
private void handleRefreshButton(ActionEvent event) {
try {
textField.setText("");
FXMLLoader loader = new FXMLLoader(getClass().getResource("child.fxml"));
Parent parent = loader.load();
childViewController = loader.getController();
childViewController.addConsumer(textField::setText);
childContainer.getChildren().setAll(parent);
}
catch (IOException e) {
e.printStackTrace();
}
}
}