'How to communicate between a dialog and parent Controller in javaFX

I have a MainController and when I press a certain button, a custom dialog (loaded from a custom FXML file) pops up from that MainController class. Now, in that dialog, there are some text input fields and a button. When I press that button, the dialog should close and the data from the input fields should be sent to the parent controller (which is the MainController in this case). So far I have thought of an approach:

  1. First, by using a singleton class to store the values
  2. Second, by sending the dialog instance through the loader method during the creation of the dialog
DialogController dialogController = loader.getController();
dialogController.setContent(dialog);

But this way, I fear there will be memory leaks and such. Is there any better way to do this, such as using interfaces? Some help will be really appreciated!

My code so far:

MainController.java

 private void openDialog() {
        try {
            JFXDialogLayout content = new JFXDialogLayout();
            FXMLLoader loader = new FXMLLoader(getClass().getResource("dialogs/dialog.fxml"));
            loader.load();
            JFXDialog dialog = new JFXDialog(stackPaneRoot, loader.getRoot(), JFXDialog.DialogTransition.CENTER);
            DialogController dialogController = loader.getController();
            dialogController.setContent(dialog);
            dialog.show();
        } catch (Exception e) {
            e.printStackTrace();
     }
 }

DialogController.java

public class DialogController {

    @FXML
    private TextField nameInput;
    private JFXDialog dialog;

    @FXML
    void onCloseClick(ActionEvent event) {
        dialog.close();
        // Util is the singleton class to store the data
        Util.getInstance().setName(nameInput.getText());
    }

    public void setContent(JFXDialog dialog) {
        this.dialog = dialog;
    }
}


Solution 1:[1]

In my app, I ended up with the below. Basically, I call my addUser method on my main view when a user clicks "Add User" button. I set the pane of my plain Dialog object to my NewUserDialog.fxml (I am using scene builder btw). You'll see in my example below. It's the most eloquent way of doing it that I've found without having to resort to static classes.

Note that, my NewUserDialog.fxml cannot contain a reference to a controller, because in the FXMLLoader object, we use setController method to pass in the controller we instantiate. We wait for the user to select Apply, and then call the public controllers getData() method, which just returns a string of the firstNameField.

This way, you can inject objects into the controller class with a constructor or method, or just create a public function in the controller that returns an object model of your data and go from there.

private void addUser(ActionEvent event) {
        newDialog = new Dialog();
        FXMLLoader loader = new FXMLLoader(app.getClass().getResource("fxml/NewUserDialog.fxml"));
        newUserController = new NewUserDialogController();
        loader.setController(newUserController);
        try {
            newDialog.setDialogPane(loader.load());   
        } catch (Exception e) {
            throw new Error("Add user dialog class could not load: \n" + e);
        }
        
        Optional<ButtonType> result = newDialog.showAndWait();
        if (result.get() == ButtonType.APPLY){
            System.out.println(newUserController.getData());
        } else {
            System.out.println("Cancel");
        }
}

And this is my dialog controller

public class NewUserDialogController implements Initializable {

@FXML
private TextField firstNameField;
@FXML
private TextField lastNameField;
@FXML
private TextField middleNameField;
@FXML
private TextField profileNameField;
@FXML
private ComboBox<?> roleComboBox;

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

public String getData() {
    return firstNameField.getText();
}
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 J T