Search code examples
javadialogjavafxfxmlstage

JavaFX Dialogbox communication


I am new to JavaFX and trying to create an Confirmation Dialogbox. I know already that there is no real build in dialogbox in JavaFX so I created one myself like this:

@FXML
public void delBox() {
     try {
        Stage dialogStage = new Stage();
        AnchorPane root = FXMLLoader.load(getClass().getResource("Dialog.fxml"));
        Scene scene = new Scene(root);
        dialogStage.setScene(scene);
        dialogStage.showAndWait();
    } catch(Exception e) {
        e.printStackTrace();
    } 
}

It looks pretty good already, but what I dont understand is, how those two Stages can communicate with each other? I want to pass a String to the dialog which is than shown in the message, also when one of the buttons in the dialog window is clicked I wanna react to this in the accordingly.

Can anyone explain me how communication between the stages works? btw: I use .FXML files and controller classes.


Solution

  • You need a reference to the controller for the dialog. To do this, create an instance of FXMLLoader instead of using the static FXMLLoader.load(URL) method.

    For example, suppose you have a class DialogController, so your Dialog.fxml looks like:

    <AnchorPane xmlns:fx="..." fx:controller="DialogController.fxml">
    ...
    </AnchorPane>
    

    Then you can access the DialogController in the delBox() method above with

    Stage dialogStage = new Stage();
    FXMLLoader loader = new FXMLLoader(getClass().getResource("Dialog.fxml"));
    AnchorPane root = (AnchorPane)loader.load();
    DialogController controller = (DialogController) loader.getController();
    Scene scene = new Scene(root);
    dialogStage.setScene(scene);
    dialogStage.showAndWait();
    

    And now you can communicate between the two controllers. For example, in DialogController you could define a message property, and bind it to a Label :

    public class DialogController {
        private final StringProperty message = new SimpleStringProperty("");
        public void setMessage(String message) {
            this.message.set(message);
        }
        public String getMessage() {
            return message.get();
        }
        public StringProperty messageProperty() {
            return message ;
        }
    
        @FXML
        private Label label ;
    
        public void initialize() {
            label.textProperty().bind(message);
            // ...
        }
    }
    

    And then back in your delBox() method:

    //... as before:
            AnchorPane root = (AnchorPane)loader.load();
            DialogController controller = (DialogController) loader.getController();
            controller.setMessage("Hello World");
    // ...
    

    Similarly, you can define properties which are set when controls are pressed in the dialog itself, and either observe them or query them after the showAndWait() call.

    There are a bunch of other similar techniques. Some examples:

    https://github.com/james-d/Shared-Data-Controller/tree/master/src

    https://github.com/james-d/Dialog-FXML-Example/tree/master/src

    https://github.com/james-d/Nested-Controller-Example/tree/master/src/nestedcontrollerexample