3 Replies Latest reply: Apr 1, 2013 1:38 PM by James_D RSS

    FXML/Controller - Notify Controller from other Controller

    564776
      I have two Controllers and FXML, where the Controller 1 has a TableView, showing data from database.

      The Controller 2 adds objects to database, and i´d like know how to notify the other controller to refresh the tableview data.

      Thanks.
        • 1. Re: FXML/Controller - Notify Controller from other Controller
          James_D
          Arrange for both controllers to have references to a single ObservableList containing the data. Depending on how your application is structured you can do this by setting the controller directly on the FXMLLoader, or setting a controller factory which instantiates the controllers with a reference to the ObservableList. {thread:id=2508774} has some examples of doing something similar.

          The controller managing the table view should call table.setItems(data) in its initialize() method. The controller adding data to the database should add an item to the observable list when the database update is successful. This will automatically update the table.
          • 2. Re: FXML/Controller - Notify Controller from other Controller
            564776
            so, i need to send the observablelist reference to controller ?
            • 3. Re: FXML/Controller - Notify Controller from other Controller
              James_D
              Yes. I would instantiate the ObservableList and then set a controller factory that instantiates the relevant controllers, passing them the ObservableList instance.

              Here's the canonical contact list example:

              Person.java
              import javafx.beans.property.SimpleStringProperty;
              import javafx.beans.property.StringProperty;
              
              public class Person {
                   private final StringProperty firstName;
                   private final StringProperty lastName;
              
                   Person(String firstName, String lastName) {
                        this.firstName = new SimpleStringProperty(this, "firstName", firstName);
                        this.lastName = new SimpleStringProperty(this, "lastName", lastName);
                   }
              
                   public String getFirstName() {
                        return firstName.get();
                   }
              
                   public void setFirstName(String firstName) {
                        this.firstName.set(firstName);
                   }
              
                   public StringProperty firstNameProperty() {
                        return firstName;
                   }
              
                   public String getLastName() {
                        return lastName.get();
                   }
              
                   public void setLastName(String lastName) {
                        this.lastName.set(lastName);
                   }
              
                   public StringProperty lastNameProperty() {
                        return lastName;
                   }
              }
              TableExample.java
              import java.io.IOException;
              
              import javafx.application.Application;
              import javafx.collections.FXCollections;
              import javafx.collections.ObservableList;
              import javafx.fxml.FXMLLoader;
              import javafx.scene.Parent;
              import javafx.scene.Scene;
              import javafx.stage.Stage;
              import javafx.util.Callback;
              
              public class TableExample extends Application {
              
                @Override
                public void start(Stage primaryStage) throws IOException {
                  final ObservableList<Person> personList = FXCollections.observableArrayList();
                  final Callback<Class<?>, Object> controllerFactory = new Callback<Class<?>, Object>() {
                    @Override
                    public Object call(Class<?> clazz) {
                      if (clazz == EditorController.class) {
                        return new EditorController(personList);
                      } else if (clazz == TableController.class) {
                        return new TableController(personList);
                      } else
                        try {
                          return clazz.newInstance();
                        } catch (InstantiationException | IllegalAccessException e) {
                          return null;
                        }
                    }
                  };
                  final FXMLLoader loader = new FXMLLoader(getClass().getResource("Main.fxml"));
                  loader.setControllerFactory(controllerFactory);
                  Parent root = (Parent) loader.load();
                  primaryStage.setScene(new Scene(root, 600, 600));
                  primaryStage.show();
                }
              
                public static void main(String[] args) {
                  launch(args);
                }
              }
              Main.fxml
              <?xml version="1.0" encoding="UTF-8"?>
              
              <?import javafx.scene.layout.BorderPane?>
              
              <BorderPane xmlns:fx="http://javafx.com/fxml">
                   <center>
                        <fx:include source="Table.fxml" />
                   </center>
                   <bottom>
                        <fx:include source="Editor.fxml" />
                   </bottom>
              </BorderPane>
              Table.fxml
              <?xml version="1.0" encoding="UTF-8"?>
              
              <?import javafx.scene.layout.BorderPane?>
              <?import javafx.scene.control.TableView?>
              <?import javafx.scene.control.TableColumn?>
              <?import javafx.scene.control.cell.PropertyValueFactory?>
              
              <BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="TableController">
                   <center>
                        <TableView fx:id="table">
                             <columns>
                                  <TableColumn text="First Name">
                                       <cellValueFactory>
                                            <PropertyValueFactory property="firstName" />
                                       </cellValueFactory>
                                  </TableColumn>
                                  <TableColumn text="Last Name">
                                       <cellValueFactory>
                                            <PropertyValueFactory property="lastName" />
                                       </cellValueFactory>
                                  </TableColumn>
                             </columns>
                        </TableView>
                   </center>
              </BorderPane>
              Editor.fxml
              <?xml version="1.0" encoding="UTF-8"?>
              
              <?import javafx.scene.layout.GridPane?>
              <?import javafx.scene.control.Label?>
              <?import javafx.scene.control.TextField?>
              <?import javafx.scene.control.Button?>
              
              
              <GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="EditorController">
                   <Label text="First name:" GridPane.columnIndex="0" GridPane.rowIndex="0" />
                   <TextField fx:id="firstNameTextField" GridPane.columnIndex="1" GridPane.rowIndex="0" />
                   <Label text="Last name:" GridPane.columnIndex="0" GridPane.rowIndex="1" />
                   <TextField fx:id="lastNameTextField" GridPane.columnIndex="1" GridPane.rowIndex="1" />
                   <Button text="Add" onAction="#addPerson" GridPane.columnIndex="0" GridPane.rowIndex="2" />
              </GridPane>
              TableController.java
              import javafx.collections.ObservableList;
              import javafx.fxml.FXML;
              import javafx.scene.control.TableView;
              
              public class TableController {
                   private final ObservableList<Person> personList;
              
                   @FXML
                   private TableView<Person> table;
              
                   public TableController(ObservableList<Person> personList) {
                        this.personList = personList;
                   }
              
                   public void initialize() {
                        table.setItems(personList);
                   }
              }
              EditorController.java
              import javafx.collections.ObservableList;
              import javafx.fxml.FXML;
              import javafx.scene.control.TextField;
              
              public class EditorController {
                   private final ObservableList<Person> personList;
                   @FXML
                   private TextField firstNameTextField;
                   @FXML
                   private TextField lastNameTextField;
              
                   public EditorController(ObservableList<Person> personList) {
                        this.personList = personList;
                   }
              
                   @FXML
                   private void addPerson() {
                        final String firstName = firstNameTextField.getText();
                        final String lastName = lastNameTextField.getText();
                        final Person newPerson = new Person(firstName, lastName);
                        // Do database update here
                        personList.add(newPerson);
                   }
              }
              Obviously, if there were more data to be shared between the controllers, you could create a class encapsulating it all. This is basically implementing the Model-View-Controller design pattern. The ObservableList in this example is the Model; the controllers update the model and the views (defined by FXML) observe the model and update accordingly when the data in it changes.