Skip to content
Advertisement

Prevent JavaFX dialog from closing

I’m currently creating a dialog using JavaFX. The Dialog it self works very well but now I’m trying to add an input validation which warns the user when he forgets to fill out a text field. And here comes my question: Is it possible to prevent the dialog from closing inside the Result Converter? Like this:

ButtonType buttonTypeOk = new ButtonType("Okay", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().add(buttonTypeOk);

dialog.setResultConverter((ButtonType param) -> {   

    if (valid()) {
        return ...
    } else {
        Alert alert = new Alert(Alert.AlertType.WARNING);
        alert.setHeaderText("Pleas fill all fields!");
        alert.showAndWait();
        //prevent dialog from closing
    }

});

I noticed that the dialog dosn’t close if an error was thrown inside the resault converter but this doesn’t seems to be a good way to solve this problem.

If it isn’t possible to solve the problem this way I could disable the button as described in this post. But I would prefer to keep the button enabled and display a message.

Thank you in advance !

Advertisement

Answer

How you are supposed to manage data validation in a dialog is actually explained in the Javadoc, I quote:

Dialog Validation / Intercepting Button Actions

In some circumstances it is desirable to prevent a dialog from closing until some aspect of the dialog becomes internally consistent (e.g. a form inside the dialog has all fields in a valid state). To do this, users of the dialogs API should become familiar with the DialogPane.lookupButton(ButtonType) method. By passing in a ButtonType (that has already been set in the button types list), users will be returned a Node that is typically of type Button (but this depends on if the DialogPane.createButton(ButtonType) method has been overridden). With this button, users may add an event filter that is called before the button does its usual event handling, and as such users may prevent the event handling by consuming the event. Here’s a simplified example:

final Button btOk = (Button) dlg.getDialogPane().lookupButton(ButtonType.OK);
btOk.addEventFilter(
    ActionEvent.ACTION, 
    event -> {
        // Check whether some conditions are fulfilled
        if (!validateAndStore()) {
            // The conditions are not fulfilled so we consume the event
            // to prevent the dialog to close
            event.consume();
        }
    }
);

In other words, you are supposed to add an event filter to your button to consume the event in case the requirements are not fulfilled which will prevent the dialog to be closed.

More details here

Advertisement