0

I have a modal class:

public class DialogModal
{
    private String fxmlURL;
    private int width;
    private int height;

    public DialogModal( String url, int w, int h )
    {
        fxmlURL = url;
        width = w;
        height = h;
    }

    public void showDialogModal(Button root) throws IOException
    {
        Stage modalDialog = new Stage();
        FXMLLoader loader = new FXMLLoader(getClass().getResource( fxmlURL ));
        Parent modalDialogRoot = loader.load();
        Scene modalScene = new Scene( modalDialogRoot, width, height );
        modalScene.getStylesheets().add(InventoryManager.class.getResource("InventoryManager.css").toExternalForm());
        modalDialog.initOwner(root.getScene().getWindow());
        modalDialog.setScene(modalScene);
        modalDialog.setResizable(false);
        modalDialog.showAndWait();
    }
}

which is then opened thusly (from an FXML controller):

    @FXML
    private void handleModalButton(ActionEvent e) throws IOException
    {
        DialogModal modal = new DialogModal("Modal.fxml", 400, 450);
        modal.showDialogModal((Button)e.getSource());
    }

My question is, how do I get data from the modal (i.e., TextFields) back to my handleModalButton method? This modal can be given different FXML files, so the data that it returns may be different.

Additionally, how do (or should) I send data to the modal (e.g., to populate TextFields)?

Thanks!

Tomás Gray
  • 49
  • 1
  • 1
  • 8
  • For passing data there are some approaches presented here. https://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml You should also find information about how to access the controller in there. You should probably add some kind of interface to the controller classes to establish a communication that does not depend on the controller classes. – fabian Jun 05 '18 at 23:19

1 Answers1

1

You can make DialogModal.showDialogModal() return the controller of the spawned modal dialog window.

public <T> T showDialogModal(Button root) throws IOException
{
    Stage modalDialog = new Stage();
    FXMLLoader loader = new FXMLLoader(getClass().getResource( fxmlURL ));
    Parent modalDialogRoot = loader.load();
    T controller = loader.getController(); // Retrieve the controller
    Scene modalScene = new Scene( modalDialogRoot, width, height );
    modalScene.getStylesheets().add(InventoryManager.class.getResource("InventoryManager.css").toExternalForm());
    modalDialog.initOwner(root.getScene().getWindow());
    modalDialog.setScene(modalScene);
    modalDialog.setResizable(false);

    // You need Platform.runLater() so that this method doesn't get blocked
    Platform.runLater(() -> modalDialog.showAndWait());

    return controller; // Return the controller back to caller
}

Then in your calling method:

@FXML
private void handleModalButton(ActionEvent e) throws IOException
{
    DialogModal modal = new DialogModal("Modal.fxml", 400, 450);
    FooController controller = modal.showDialogModal((Button)e.getSource());

    String data1 = controller.getTextField1Data();
    // ...
}

You need to know exactly the class of the controller in handleModalButton(), otherwise you are going to get a ClassCastException. Of course, you need to have public getters in the controller that exposes the necessary values. You can keep things like nodes and setters private though.

If you have multiple methods similar to handleModalButton(), and for all of them, you need get a similar set of values, then you can consider creating an interface, which all your controller classes can implement. The interface will include getter methods that you can get the data from. Then showDialogModal() can return the interface type, and the calling method can get the references of the controller objects via the interface type.

Jai
  • 8,165
  • 2
  • 21
  • 52