To share data between the scenes, we'll introduce a Model
class that holds the shared information:
public class Model {
private SimpleStringProperty valueProperty = new SimpleStringProperty("N/A");
public SimpleStringProperty getValueProperty() {
return valueProperty;
}
}
And an interface to be implemented by the controllers of the two scenes (actually the controllers of the two roots of the two scenes).
The interface adds the functionality of injection a Model
into the controller:
public interface Controller {
void setModel(Model model);
}
sceneOne.fxml
with a button to switch scene and a label to display user's input:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
prefHeight="300.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/16"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="SceneOneController">
<children>
<Label layoutX="159.0" layoutY="40.0" text="Scene 1">
<font>
<Font size="24.0" />
</font>
</Label>
<Button layoutX="264.0" layoutY="246.0" mnemonicParsing="false" onAction="#changeScene" prefHeight="26.0" prefWidth="102.0" text="Get Input" />
<Label fx:id="inputValue" layoutX="187.0" layoutY="142.0" text="Label" />
</children>
</AnchorPane>
And its controller which implements the Controller
interface:
public class SceneOneController implements Controller {
@FXML Label inputValue;
private Model model;
public void changeScene(ActionEvent e) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("sceneTwo.fxml"));
Parent root = loader.load();
Controller controller = loader.getController(); //get a reference to sceneTwo controller
controller.setModel(model);
Stage stage = (Stage)((Node)e.getSource()).getScene().getWindow();
stage.setScene(new Scene(root));
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void setModel(Model model) {
this.model = model;
if(model != null){
inputValue.textProperty().unbind();
inputValue.textProperty().bind(model.valueProperty);
}
}
}
sceneTwo.fxml
with a button to switch scene and a TextField for the user's input:
<?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.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="main" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="SceneTwoController">
<children>
<Label layoutX="150.0" layoutY="41.0" text="Scene 2">
<font>
<Font size="24.0" />
</font>
</Label>
<Button layoutX="264.0" layoutY="246.0" mnemonicParsing="false" onAction="#changeScene" prefHeight="26.0" prefWidth="102.0" text="Update" />
<TextField fx:id="inputValue" layoutX="121.0" layoutY="138.0" prefHeight="25.0" prefWidth="162.0" />
</children>
</AnchorPane>
And its controller:
public class SceneTwoController implements Controller {
@FXML TextField inputValue;
private Model model;
public void changeScene(ActionEvent e) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("sceneOne.fxml"));
Parent root = loader.load();
Controller controller = loader.getController(); //get a reference to sceneOne controller
controller.setModel(model);
Stage stage = (Stage)((Node)e.getSource()).getScene().getWindow();
stage.setScene(new Scene(root));
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void setModel(Model model) {
this.model = model;
if(model != null){
inputValue.textProperty().unbind();
model.valueProperty.bind(inputValue.textProperty());
}
}
}
And finally the application to test it all:
public class SwitchSceneMVC extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("sceneOne.fxml"));
Parent root = loader.load();
Model model = new Model();
Controller controller = loader.getController();
controller.setModel(model);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(null);
}
}