Most of programs in this world would need to pass different data and arguments between the different layouts and screens, so we will explain the easiest way to have this done in JavaFX in this tutorial.

Structure

In our demonstration, we will create the following files:

  • Main.java
  • layout1.fxml
  • layout2.fxml
  • controller1.java
  • controller2.java

Our program will open our main java class which request layout1 with its controller (controller1) to be displayed, so we will keep the default codes in our main.java:

1
2
3
4
Parent root = FXMLLoader.load(getClass().getResource("layout1.fxml"));
primaryStage.setTitle("Layout1 + Controller1");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();

The Plan

We will have a textfield and a button in layout1, and we want to display layout2 with a label of the text that was entered in this textfiled after the button is clicked in layout1.

pass a value from one fxml to another

Steps

  1. Add controls to layout1 and layout2

layout1:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
   <?xml version="1.0" encoding="UTF-8"?>
   <?import javafx.scene.control.Button?>
   <?import javafx.scene.control.TextField?>
   <?import javafx.scene.layout.AnchorPane?>
   
   <AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.172-ea" 
               xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller1">
      <children>
         <TextField fx:id="textfield" layoutX="195.0" layoutY="110.0" />
         <Button fx:id="button" layoutX="194.0" layoutY="169.0" mnemonicParsing="false" text="Take this value to layout2" onMouseClicked="#buttonClicked" />
      </children>
   </AnchorPane>

layout2:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
   <?xml version="1.0" encoding="UTF-8"?>
   <?import javafx.scene.control.Label?>
   <?import javafx.scene.layout.AnchorPane?>
   
   <AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.172-ea"
               xmlns:fx="http://javafx.com/fxml/1" 
               fx:controller="controller2">
      <children>
         <Label fx:id="label" layoutX="283.0" layoutY="145.0" text="Label" />
      </children>
   </AnchorPane>
  1. We will create a method in controller2 that will set the text of the label inside layout2:
1
2
3
   public void setLabelText(String text){
       label.setText(text);
   }
  1. Now we will need add an addition to our usual way when displaying a new stage in JavaFX, so we will be able to call setLabelText() method within controller1
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
   public void buttonClicked(){
   
       try {
           FXMLLoader loader = new 		  FXMLLoader(getClass().getResource("layout2.fxml"));
           Parent root = loader.load();
   
           //The following both lines are the only addition we need to pass the arguments
           controller2 controller2 = loader.getController();
           controller2.setLabelText(textfield.getText());
   
           Stage stage = new Stage();
           stage.setScene(new Scene(root));
           stage.setTitle("Layout2 + Controller2");
           stage.show();
   
       } catch (IOException e) {
           e.printStackTrace();
       }
   }

Note: We need to specify the controllers within fxml layouts like usual.

Sending values back and updating the items on the layout1 UI

Till here we are done with how to pass values, but what if we wanted to send some data back to layout1 without reloading the same layout?

For example, we will add another button to layout2 and display “Welcome” inside textfield on layout1 once it is clicked. We can do this easily with following approach:

  • We will need to pass the textfield as an argument when we call setLabelText() within controller1:

    1
    2
    3
    4
    5
    6
    7
    8
    
    public void buttonClicked(){
    
        try {
        ...
        controller2.setLabelText(textfield.getText(), textfield);
        ...
        }
    }
    • We will init the passed textfield to a local TextFiled within controller2.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
       ...
    
       @FXML TextField textfield;
    
       ...
    
       public void setLabelText(String text, TextField textfield){
           label.setText(text);
           this.textfield = textfield;
       }
  • Now, we can update or do what we want with the new textfield inside controller2 and the same updates will be applied on the passed textfield.

    1
    2
    3
    4
    
    public void buttonWelcomeClicked(){
        textField.setText("Welcome");
    
    }

    send data back from popup in javafx