Reputation: 4781
I currently have a dialog with four TextFields from which the input is collected. When the input can not meet my requirements, the dialog should stay open and show an error message. I currently have the following code:
dlg.setResultConverter(dialogButton -> {
if (dialogButton == createButtonType) {
ArrayList<String> returnList = getInput();
if (returnList != null) {
return returnList;
}
else {
dlg.showAndWait();
}
}
return null;
});
Optional<ArrayList<String>> result = dlg.showAndWait();
result.ifPresent(customerDetails -> {
//Use the input for something
});
The getInput()
method gets the text from the TextFields and tests it against some requirements. When the input passes, the four Strings are put in an ArrayList<String>
. Else, the method returns null
. As you can see, the result converter checks if the method returned null
. If it didn't, it just returns the ArrayList<String>
.
But, when the validation fails, the dialog should be kept open. It works with dlg.showAndWait()
, but the downside is that it triggers an error: java.lang.IllegalStateException: Stage already visible
. (it keeps working, but getting an error is not the way it should be)
My question is: does anyone know how to do this, without triggering an error?
Note: I am using JavaFX 8 (JDK 1.8.0_40), which has the dialog features built in.
Upvotes: 10
Views: 7922
Reputation: 14287
Assume a Dialog with TextField and an Ok Button.
The button is disabled to start with and is enabled on entering valid data in the TextField (text between 5 and 25 characters long). The ChangeListener attached to the TextField's StringProperty controls the button's enabled/disabled state.
TextField textFld = new TextField();
...
ButtonType buttonTypeOk = new ButtonType("Okay", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().add(buttonTypeOk);
final Button okButton = (Button) dialog.getDialogPane().lookupButton(buttonTypeOk);
okButton.setDisable(true);
textFld.textProperty().addListener((observable, oldValue, newValue) -> {
okButton.setDisable(newValue.trim().length() < 5 || newValue.trim().length() > 25);
});
Upvotes: 0
Reputation: 1210
final Button okButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
okButton.addEventFilter(ActionEvent.ACTION, ae -> {
if (!isValid()) {
ae.consume(); //not valid
}
});
Works fine for me. Just use filter as it fires first.
BTW it is described in official docs.
Upvotes: 24
Reputation: 11134
Add listeners to your TextField
s, validating the user input.
If the user input is valid, enable the "OK" Button
(or whatever its name is) if the user input is invalid, disable the Button
.
If the Button
for closing the Dialog
is disabled, the only way to close the Dialog
is to cancel, which results in an empty Optional
as result.
Upvotes: 7