JavaFX. Communication between controllers


Question

Hello I'm starting in JavaFX and I've got some problems. I want to communicate two controlles from two diferents views. How can I do it? I'm working with tabs and i have this two controllers and i want to do something similar like this:

Application.java:

public class JavaFXApplication6 extends Application 
{

@Override
public void start(Stage primaryStage) 
{
    try 
    {
        Parent root = FXMLLoader.load(getClass().getResource(
                "/view/FXML_Main.fxml"));
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    } catch(Exception e){
        e.printStackTrace();
    }

    primaryStage.setTitle("Back-end GUI");
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) 
{
    launch(args);
}

}

FXML_Main.fxml:

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>


<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" 
    xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" 
    fx:controller="controller.FXML_MainController">
   <children>
      <TabPane layoutX="61.0" layoutY="30.0" prefHeight="400.0" prefWidth="600.0" 
         tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" 
         AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" 
         AnchorPane.topAnchor="0.0">
        <tabs>
          <Tab text="Untitled Tab 1">
               <content>
                  <fx:include source="FXML_Tab1.fxml" />
               </content>
          </Tab>
          <Tab text="Untitled Tab 2">
               <content>
                  <fx:include source="FXML_Tab2.fxml" />
               </content>
          </Tab>
        </tabs>
      </TabPane>
   </children>
</AnchorPane>

FXML_MainController.java:

public class FXML_MainController implements Initializable {

/**
 * Initializes the controller class.
 */
@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
}    

}

FXML_Tab1.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0"
     xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" 
     fx:controller="controller.FXML_Tab1Controller">
<children>
  <Label fx:id="Label1" layoutX="282.0" layoutY="108.0" text="Label" />
  <TextField fx:id="FextField1" layoutX="215.0" layoutY="146.0" />
  <Button fx:id="Button1" layoutX="269.0" layoutY="197.0" mnemonicParsing="false"
      onAction="#actionButton1" text="Button" />
</children>
</AnchorPane>

FXML_Tab1Controller.java:

public class FXML_Tab1Controller implements Initializable {

FXML_Tab2Controller tab2controller;

@FXML public Label Label1;
@FXML public TextField TextField1;
@FXML public Button Button1;
/**
 * Initializes the controller class.
 */
@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
} 

@FXML private void actionButton1(ActionEvent event)
{
    Label1.setText(tab2controller.TextField2.getText());
}

}

FXML_Tab2.fxml:

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" 
    xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" 
    fx:controller="controller.FXML_Tab2Controller">
   <children>
      <Label fx:id="Label2" layoutX="282.0" layoutY="99.0" text="Label" />
      <TextField fx:id="TextField2" layoutX="215.0" layoutY="149.0" />
      <Button fx:id="Button2" layoutX="270.0" layoutY="200.0" mnemonicParsing="false" 
    onAction="#actionButton2" text="Button" />
   </children>
</AnchorPane>

FXML_Tab2Controller.java:

public class FXML_Tab2Controller implements Initializable {

FXML_Tab1Controller tab1controller;
@FXML public Label Label2;
@FXML public TextField TextField2;
@FXML public Button Button2;
/**
 * Initializes the controller class.
 */
@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
} 

@FXML private void actionButton2(ActionEvent event){
        Label2.setText(tab1controller.TextField1.getText());
}

}

something similar like that video: https://www.youtube.com/watch?v=XLVx46ycxco

1
0
11/14/2016 9:20:49 PM

Add an fx:id to each of your <fx:include> tags:

    <tabs>
      <Tab text="Untitled Tab 1">
           <content>
              <fx:include source="FXML_Tab1.fxml" fx:id="tab1" />
           </content>
      </Tab>
      <Tab text="Untitled Tab 2">
           <content>
              <fx:include source="FXML_Tab2.fxml" fx:id="tab2" />
           </content>
      </Tab>
    </tabs>

This will allow you to inject the corresponding controllers into your FXML_MainController:

public class FXML_MainController  {

    @FXML
    private FXML_Tab1Controller tab1Controller ;
    @FXML
    private FXML_Tab2Controller tab2Controller ;

}

The variable naming is very important here: the fields must be named xController where x is the value for the fx:id attribute in the fx:include. See the Introduction to FXML documentation for details.

Now in your main controller's initialize() method, you can establish the relationship between the two controllers:

public class FXML_MainController  {

    @FXML
    private FXML_Tab1Controller tab1Controller ;
    @FXML
    private FXML_Tab2Controller tab2Controller ;

    public void initialize() {
        tab1Controller.tab2Controller = tab2Controller ;
        tab2Controller.tab1Controller = tab1Controller ;
    }
}
4
10/27/2014 3:27:09 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon