Question

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.

Was it helpful?

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

OTHER TIPS

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

FX Controller is a java file, so it has to be DialogController and the Controller's path should be included i.e, fx:controller="applicationPackageName.DialogController"
The above mentioned fxml code does not work. It results in
javafx.fxml.LoadException
java.lang.InstantiationException
java.lang.NoSuchMethodException

Reason: The jvm looks for a class constructor with 0 parameters to build an instance. To overcome the error, the controller file needs to be loaded in the function coded in java:
loader.setController(new ControllerName(""));

To sum up (Working code):
FXML file:

<BorderPane id="background" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="240.0" prefWidth="320.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" >
    <bottom>
        <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
            <children>
                <Button onAction="#close" text="OK" />
            </children>             
        </HBox>
    </bottom>
    <center>
        <Label fx:id="messageLabel" />
    </center>
</BorderPane>

Controller file:

public class PiPreferenceController {
     private final String message ;

        @FXML
        private Label messageLabel ;

        @FXML
        void initialize() {
            messageLabel.setText(message);
        }



        public PiPreferenceController(String message) {
            this.message = message ;
        }



        @FXML
        public void close() {
            messageLabel.getScene().getWindow().hide();
        }

}


Function:

void dialogPreferences() throws IOException {

        Stage dialogStage = new Stage();
        FXMLLoader loader = new FXMLLoader(getClass().getResource(
                "PiPreference.fxml"));

        loader.setController(new PiPreferenceController(""));
        BorderPane root = (BorderPane) loader.load();
        Scene scene = new Scene(root);
        dialogStage.setScene(scene);
        dialogStage.showAndWait();

    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top