JavaFX Dialog: Run onClosingRequest only when Ok button pressed - java

I have a form Dialog and I want to add a confirmation alert before the dialog closes.
The dialog is not to close until confirmed Ok.
This I can prevent by consuming the event.
It should only confirm on clicking the Dialog Ok, not on Cancel.
Problem is, I cannot see which button was clicked on the event. So the Alert confirmation is shown for both OK and CANCEL buttons on the dialog.
How can I prevent the onClosingReqeust for cancel button?
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
public class DialogTestApplication extends Application {
public static void main(String[] args) {
launch(args);
}
class MyDialog extends Dialog<ButtonType> {
public MyDialog(Window window) {
setTitle("MyDialog");
initModality(Modality.WINDOW_MODAL);
initOwner(window);
setResizable(true);
GridPane contentPane = new GridPane();
contentPane.add(new TextField(), 0, 0);
getDialogPane().setContent(contentPane);
getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
setOnCloseRequest(event -> {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.showAndWait().ifPresent(response -> {
if (response == ButtonType.CANCEL) {
event.consume();
}
});
});
}
}
#Override
public void start(Stage primaryStage) throws Exception {
final StackPane root = new StackPane();
final Label rootLabel = new Label("DialogTestApplication");
root.getChildren().add(rootLabel);
final Scene scene = new Scene(root, 400, 150);
primaryStage.setScene(scene);
primaryStage.setTitle("DialogTestApplication");
primaryStage.show();
Platform.setImplicitExit(true);
MyDialog dialog = new MyDialog(primaryStage);
dialog.showAndWait().ifPresent(response -> {
if (response == ButtonType.OK) {
System.out.println("OK");
}
Platform.exit();
});
}
}

After reading the Dialog Javadoc I found a solution that works.
https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Dialog.html
Button button = (Button) getDialogPane().lookupButton(ButtonType.OK);
button.addEventFilter(ActionEvent.ACTION, event -> {
final Alert alert = new Alert(AlertType.CONFIRMATION);
alert.initOwner(window);
alert.showAndWait().ifPresent(response -> {
if (response == ButtonType.CANCEL) {
event.consume();
}
});
});

final Button btnCancel = (Button) dialog.getDialogPane().lookupButton( ButtonType.CANCEL);
btnCancel.addEventFilter(ActionEvent.ACTION, event -> {
// handle cancel button code here
event.consume();
});
public boolean displayDialog() {
Optional<ButtonType> result = dialog.showAndWait();
if(result.get().getText().equals("Ok")) {
//handle OK action. The dialog panel will close automatically.
}
return true;
}
Handle the cancel button event when instantiating the alert. The event.consume() method will prevent the alert dialog from closing when pressing CANCEL. You can add a method to display your alert, within that method handle the OK action.

You can handle action event of the OK button instead of handling close request of the dialog. Something like this
// I tested with onMouseClicked but the event doesn't get fired
// onAction on the other hand works normally but we need to cast the node to a button
Button button = (Button) getDialogPane().lookupButton(ButtonType.OK);
button.setOnAction(e -> {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.showAndWait().ifPresent(response -> {
if (response == ButtonType.CANCEL) {
event.consume();
}
});
});

Related

JavaFX - Why does changing the header text of a dialog make the button bar invisible?

Here is a small sample from my custom dialog, which is meant to display the progress of a running javafx.concurrent.Task.
DialogPane pane = this.getDialogPane()
pane.getButtonTypes().addAll(ButtonType.CANCEL);
pane.headerTextProperty().bind(task.titleProperty());
pane.contentTextProperty().bind(task.messageProperty());
For some reason, the buttons in the button bar disappeared, but only after some text updated. After further investigation, I found that binding the header text of a dialog seems to remove all the buttons in the button bar. Why would this happen, and what would I do to stop the buttons from being hidden?
EDIT: Here's an MCVE demonstrating the problem.
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class MCVE extends Application {
public static class CustomDialog extends Dialog<ButtonType> {
public CustomDialog(Task<?> task) {
this.initModality(Modality.APPLICATION_MODAL);
DialogPane pane = this.getDialogPane();
{
pane.getButtonTypes().addAll(ButtonType.CANCEL);
pane.headerTextProperty().bind(task.titleProperty());
}
setOnCloseRequest(event -> {
if (task.isRunning()) event.consume();
});
}
}
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
StackPane root = new StackPane();
Button starter = new Button("Showcase");
starter.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
root.getChildren().add(starter);
Scene scene = new Scene(root, 500, 500);
stage.setScene(scene);
stage.show();
starter.setOnAction(event -> {
Task<Void> task = new Task<>() {
#Override
protected Void call() throws Exception {
updateTitle("Before loop");
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
if (isCancelled()) return null;
}
for (int i = 1; i <= 20; i++) {
updateTitle("loop " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
if (isCancelled()) return null;
}
}
return null;
}
};
Thread worker = new Thread(task);
worker.start();
new CustomDialog(task).showAndWait();
});
}
}
It appears that the issue needs fixing on JavaFX's end. In fact, the button bar is simply pushed out of view. There is a relatively decent workaround though. Dialog internally uses a styled GridPane to display header text and graphics, so I simply replicated that using an external GridPane and instead bound to the textProperty() of a Label.
public static class CustomDialog extends Dialog<ButtonType> {
public CustomDialog(Task<?> task) {
DialogPane pane = this.getDialogPane(); {
pane.getButtonTypes().addAll(ButtonType.CANCEL);
//construct custom header
GridPane headerRoot = new GridPane(); {
Label headerText = new Label();
//headerText is the label containing the header text
headerText.textProperty().bind(task.titleProperty());
headerRoot.add(headerText, 0, 0);
}
headerRoot.getStyleClass().addAll("header-panel");
pane.setHeader(headerRoot);
pane.setContentText("Placeholder content");
pane.getScene().getWindow().setOnCloseRequest(event -> {
if (!task.isDone()) {
event.consume();
}
});
}
}
It looks exactly the same as a default dialog, without the issue mentioned in the question above.

Moving focus using keyboard trouble

Please help.
Situation: we have VBox with a lot of buttons (and i can scroll focus up/down via arrow keys on my keyboard), but they doesn't fit on the small form so i need vertical scrolling. I apply ScrollPane - and eventually everything became good except moving focus. When i press up/down arrow keys focus stands still but affects scrolling.
I need to disable scroll by keys with ScrollPane (use only mouse!) and enable move focus by up/down arrow keys. Could You please help me, how could i do it?
Many thanks!
Here my code
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TestJavaFXScrollPane extends Application {
#Override
public void start(Stage primaryStage) {
Button btn0 = new Button("Btn0");
btn0.setOnKeyPressed((event) -> {
System.out.println("btn.KeyPressed; Code: " + event.getCode());
});
Button btn1 = new Button("Btn1");
Button btn2 = new Button("Btn2");
Button btn3 = new Button("Btn3");
VBox root = new VBox();
root.getChildren().addAll(btn0, btn1, btn2, btn3);
ScrollPane scrollPane = new ScrollPane(root);
scrollPane.setOnKeyPressed(event -> {
//if(event.getCode() == KeyCode.DOWN || event.getCode() == KeyCode.UP)
//event.consume(); // Tried to fix issue, but without result ((
});
Scene scene = new Scene(scrollPane, 100, 80);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Found solution by myself (is that correct?)
class MyEventHandler implements EventHandler<KeyEvent> {
#Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.UP) {
Object t0 = event.getSource();
if (!(t0 instanceof Button))
return;
((BehaviorSkinBase) ((Button)t0).getSkin()).getBehavior().traversePrevious();
} else if(event.getCode() == KeyCode.DOWN) {
Object t0 = event.getSource();
if (!(t0 instanceof Button))
return;
((BehaviorSkinBase) ((Button)t0).getSkin()).getBehavior().traverseNext();
}
}
public static void ProcessBurrons(Button... btns) {
if(btns == null && btns.length == 0) return;
for(Button el : btns) {
el.setOnKeyPressed(new MyEventHandler());
}
}
}

Java thread not working in view

I have a simple login window in JavaFX. When the user inserts his username and password I want to make a simple string "progress bar" in another thread while the main thread processes the inputs.
When the main thread gets to the if statement (let's say the passwords don't match) I want the progress to stop when the alert is thrown. But with this code it continues even after the alert is thrown.
public void validateLogin(ActionEvent actionEvent) throws Exception {
Thread thread = new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(loading_txt.getText().length() < 10)loading_txt.setText(loading_txt.getText() + "|");
else loading_txt.setText("|");
}
});
thread.start();
String username = username_field.getText();
String password = password_field.getText();
if (!(BCrypt.checkpw(password_field.getText(), dbHandler.getLoginByUsername(username_field.getText()).getPassword()))) {
throwAlert(Alert.AlertType.ERROR,"Login problem", "Password doesn't match.", "Wrong password. Please, check out and try it again. ");
thread.join();
return;
}
thread.join();
//other code
}
So I made a little change in the if statement and put the thread.join() before the alert. Now the progress can't be even seen.
if (!(BCrypt.checkpw(password_field.getText(), dbHandler.getLoginByUsername(username_field.getText()).getPassword()))) {
thread.join();
throwAlert(Alert.AlertType.ERROR,"Login problem", "Password doesn't match.", "Wrong password. Please, check out and try it again. ");
return;
}
How does this little change cause the progress to be seen or not to be seen? What do I have to change to stop the progressing when the alert is thrown? Could it be caused by some functionality in JavaFX?
Here is an Example, you may take the idea and apply it to your program (Explanation in comments).
import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TextField;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.scene.control.ProgressBar;
public class ProgressBarExample extends Application{
ProgressBar pb = new ProgressBar(); // your progress bar
#Override
public void start(Stage primaryStage) throws Exception {
// The structure and components are for example only
TextField password = new TextField();
Button test = new Button("Test");
HBox container = new HBox();
container.getChildren().addAll(password, test);
container.setAlignment(Pos.CENTER);
VBox root = new VBox();
root.setAlignment(Pos.CENTER);
root.getChildren().addAll(container);
// add action listener to the button
test.setOnAction(e->{
// when it's pressed add Progress bar and other stuff that are concerned with the GUI!
Platform.runLater(new Runnable(){ // always use this to update GUI components
#Override
public void run() {
root.getChildren().add(pb);
// you can add label to the root...etc
// or update your progress bar ..etc
// in a nutshell: anything needs to be updated in GUI.
}
});
Task<Boolean> validatePassword = new Task<Boolean>(){ // always use Task to do complex-long calculations
#Override
protected Boolean call() throws Exception {
return validatePassword(password); // method to validate password (see later)
}
};
validatePassword.setOnSucceeded(ee->{ // when Task finishes successfully
System.out.println("Finished");
root.getChildren().remove(pb); // remove the progress bar
if(!validatePassword.getValue()){
Alert alert = new Alert(AlertType.ERROR, "Wrong Password", ButtonType.OK);
alert.showAndWait();
}
});
validatePassword.setOnFailed(eee->{ // if it fails
System.out.println("Failed");
root.getChildren().remove(pb); // remove it anyway
});
new Thread(validatePassword).start(); // add the task to a thread and start it
});
Scene scene = new Scene(root, 300,300);
primaryStage.setScene(scene);
primaryStage.show();
}
// validate here in this method
public static boolean validatePassword(TextField password){
for(int i=0; i<99999; i++){ // suppose it is a long process
System.out.println("Processing");
}
if(password.getText().equalsIgnoreCase("Invalid")){ // suppose it's invalid, just for testing
return false
}
return true;
}
public static void main(String[] args) {
launch();
}
}
Test:

JavaFX Opening one dialog from another

I have the following workflow in my application that is causing a problem:
Click Button to Open Dialog > Open Dialog > Click Button From Dialog > Display Confirmation Alert > Upon Confirmation close the first dialog and open a new dialog
The second dialog does not allow input into the TextField. I have included a SSCE that displays the problem. One additional weird thing is that if you try to close the second dialog by clicking the 'X', and then close the Alert then I am able to type into the field.
public class DialogTest extends Application {
#Override
public void start(Stage primaryStage) {
Button button = new Button("Show Dialog");
VBox root = new VBox(10, button);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 350, 120);
primaryStage.setScene(scene);
primaryStage.show();
button.setOnAction(event -> {
Dialog<Pair<String, String>> dialog = getDialog(scene.getWindow(), "Dialog 1", true);
dialog.showAndWait();
});
}
public static void main(String[] args) {
launch(args);
}
public Dialog<Pair<String, String>> getDialog(Window owner, String title, boolean addButton) {
Dialog<Pair<String, String>> dialog = new Dialog<>();
dialog.setTitle(title);
dialog.initOwner(owner);
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
if(addButton) {
Button button = new Button("Show Dialog");
dialog.getDialogPane().setContent(button);
button.setOnAction(event -> {
Alert alert = new Alert(AlertType.CONFIRMATION, "Are you sure?", ButtonType.YES, ButtonType.NO);
alert.initOwner(owner);
if(alert.showAndWait().get() == ButtonType.YES) {
dialog.close();
Dialog<Pair<String, String>> dialog2 = getDialog(owner, "Dialog 2", false);
TextField textField = new TextField();
dialog2.getDialogPane().setContent(textField);
dialog2.getDialogPane().getScene().getWindow().setOnCloseRequest(closeEvent -> {
closeEvent.consume();
if(textField.getText().trim().isEmpty()) {
Alert alert2 = new Alert(AlertType.ERROR, "Please enter a value", ButtonType.OK);
alert2.initOwner(dialog2.getDialogPane().getScene().getWindow());
alert2.showAndWait();
}
});
dialog2.showAndWait();
}
});
}
return dialog;
}
}
Problem
As explained, you have a modality problem.
Solution
The following code will demonstrate a solution where the user is asked if he really wants to print and after printing, if the ending number is correct.
(Note, that I use a class IntField from here)
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar.ButtonData;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.Window;
public class DialogTest extends Application {
Region veil;
ProgressIndicator indicator;
IntField startingNumber = new IntField(0, 999999, 0);
IntField endingNumber = new IntField(startingNumber.getValue(), 999999, startingNumber.getValue() + 1);
ButtonType printButtonType = new ButtonType("Print", ButtonData.OK_DONE);
Stage stage;
#Override
public void start(Stage primaryStage) {
stage = primaryStage;
Button button = new Button("Print Checks");
VBox box = new VBox(10, button);
box.setAlignment(Pos.CENTER);
veil = new Region();
veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.3);");
veil.setVisible(false);
indicator = new ProgressIndicator();
indicator.setMaxHeight(60);
indicator.setMinWidth(60);
indicator.setVisible(false);
StackPane root = new StackPane(box, veil, indicator);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
button.setOnAction((event) -> {
Dialog<ButtonType> dialog
= getCheckPrintDialog(primaryStage, "Enter starting check number");
dialog.showAndWait()
.filter(result -> result == printButtonType)
.ifPresent(result -> {
// this is for this example only, normaly you already have this value
endingNumber.setValue(startingNumber.getValue() + 1);
printChecks(startingNumber.getValue(), endingNumber.getValue());
});
});
}
public static void main(String[] args) {
launch(args);
}
public <R extends ButtonType> Dialog getCheckPrintDialog(Window owner, String title) {
Dialog<R> dialog = new Dialog<>();
dialog.initOwner(owner);
dialog.setTitle(title);
dialog.getDialogPane().getButtonTypes().addAll(printButtonType, ButtonType.CANCEL);
Button btOk = (Button) dialog.getDialogPane().lookupButton(printButtonType);
btOk.addEventFilter(ActionEvent.ACTION, event -> {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "Print Checks? Are you sure?", ButtonType.YES, ButtonType.NO);
alert.showAndWait()
.filter(result -> result == ButtonType.NO)
.ifPresent(result -> event.consume());
});
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
Text from = new Text("Starting Number:");
grid.add(from, 0, 0);
grid.add(startingNumber, 1, 0);
dialog.getDialogPane().setContent(grid);
return dialog;
}
private void printChecks(int from, int to) {
Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
Thread.sleep(5000);
return null;
}
};
task.setOnSucceeded((event) -> {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "Has the last check, the number: " + endingNumber.getValue() + "?", ButtonType.YES, ButtonType.NO);
alert.initOwner(stage);
Button btnNo = (Button) alert.getDialogPane().lookupButton(ButtonType.NO);
btnNo.addEventFilter(ActionEvent.ACTION, e -> {
Dialog<ButtonType> newEndNum = new Dialog<>();
newEndNum.setTitle("Enter the ending check number");
newEndNum.initOwner(stage);
newEndNum.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
Text toUser = new Text("Ending Number:");
grid.add(toUser, 0, 0);
grid.add(endingNumber, 1, 0);
newEndNum.getDialogPane().setContent(grid);
newEndNum.showAndWait().filter(result -> result == ButtonType.CANCEL)
.ifPresent(result -> e.consume());
});
alert.showAndWait();
});
veil.visibleProperty().bind(task.runningProperty());
indicator.visibleProperty().bind(task.runningProperty());
new Thread(task).start();
}
}
Working Application
The main Window:
The Print Dialog:
After a click on Print (Alerts are localized, for me in german):
After a click on Yes the Print Dialog closes and a progress will be visible (for 5 sec. in this example)
After the Printing finishes a Dialog comes up which is asking for the correct ending number
If you click Yes all is done, if you click No another dialog opens to enter the correct ending value
I have found a point where the problem is. But because I am just beginning with JavaFx I cannot provide the "why".
It seems to me that the problem is in the dialog.close(), just after the if (alert.showAndWait().get() == ButtonType.YES).
Look like it looses some reference to the dialog when you close it or something like that (I let the experts clear this out).
As a workaround, and it works for me, is move the dialog.close() to after dialog2.showAndWait();
public Dialog<Pair<String, String>> getDialog(Window owner, String title, boolean addButton) {
Dialog<Pair<String, String>> dialog = new Dialog<>();
dialog.setTitle(title);
dialog.initOwner(owner);
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
if (addButton) {
Button button = new Button("Show Dialog");
dialog.getDialogPane().setContent(button);
button.setOnAction(event -> {
Alert alert = new Alert(AlertType.CONFIRMATION, "Are you sure?", ButtonType.YES, ButtonType.NO);
alert.initOwner(owner);
if (alert.showAndWait().get() == ButtonType.YES) {
// dialog.close(); // supressed this and placed at the bottom
Dialog<Pair<String, String>> dialog2 = getDialog(owner, "Dialog 2", false);
TextField textField = new TextField();
dialog2.getDialogPane().setContent(textField);
dialog2.getDialogPane().getScene().getWindow().setOnCloseRequest(closeEvent -> {
closeEvent.consume();
if (textField.getText().trim().isEmpty()) {
Alert alert2 = new Alert(AlertType.ERROR, "Please enter a value", ButtonType.OK);
alert2.initOwner(dialog2.getDialogPane().getScene().getWindow());
alert2.showAndWait();
}
});
dialog2.showAndWait();
dialog.close(); // new location
}
});
}
return dialog;
}
The reasons for this to happen I cannot explain, but this could be a workaround.
I hope this helps you.
In your "start" method where you create Dialog1 you should call dialog.show() instead of dialog.showAndWait().
i.e.
button.setOnAction(event -> {
Dialog<Pair<String, String>> dialog = getDialog(scene.getWindow(), "Dialog 1", true);
// dialog.showAndWait();
dialog.show();
});

JavaFX - how to know if cancel was pressed

How can I know if the OK or the Cancel Button was pressed in this JavaFX dialog.
The Dialog Code:
public String delimiter;
public void delimiterYES() throws IOException {
delimiter=new String();
TextInputDialog dialog = new TextInputDialog();
dialog.setTitle("Delimiter");
dialog.setHeaderText("Enter the delimiter");
Optional<String> result = dialog.showAndWait();
if (result.isPresent()) {
delimiter=result.get();
}
}
If a result is present, then the user pressed OK. If no result is present, then the user probably pressed cancel, but they might have just closed the dialog window using the OS close window function.
Optional<String> result = new TextInputDialog().showAndWait();
if (result.isPresent()) {
// ok was pressed.
} else {
// cancel might have been pressed.
}
To really know if a button was pressed, you can use a filter as noted in the Dialog javadoc section "Dialog Validation / Intercepting Button Actions".
final Button cancel = (Button) dialog.getDialogPane().lookupButton(ButtonType.CANCEL);
cancel.addEventFilter(ActionEvent.ACTION, event ->
System.out.println("Cancel was definitely pressed")
);
Sample code:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;
import java.util.Optional;
public class DialogSample extends Application {
#Override
public void start(Stage stage) throws Exception {
Button showButton = new Button("show");
showButton.setOnAction(event -> showDialog(stage));
showButton.setPrefWidth(100);
stage.setScene(new Scene(showButton));
stage.show();
showButton.fire();
}
private void showDialog(Stage stage) {
TextInputDialog dialog = new TextInputDialog();
dialog.initOwner(stage);
dialog.setTitle("Delimiter");
dialog.setHeaderText("Enter the delimiter");
final Button ok = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
ok.addEventFilter(ActionEvent.ACTION, event ->
System.out.println("OK was definitely pressed")
);
final Button cancel = (Button) dialog.getDialogPane().lookupButton(ButtonType.CANCEL);
cancel.addEventFilter(ActionEvent.ACTION, event ->
System.out.println("Cancel was definitely pressed")
);
Optional<String> result = dialog.showAndWait();
if (result.isPresent()) {
System.out.println("Result present => OK was pressed");
System.out.println("Result: " + result.get());
} else {
System.out.println("Result not present => Cancel might have been pressed");
}
}
public static void main(String[] args) {
Application.launch();
}
}
Ok, I found the answere here JavaFX Dialogs
The result.isPresent() will return false if the user cancelled the dialog.
You can use Optional<ButtonType> instead of Optional<String>. And basically use the below code.
Optional<ButtonType> result = dialog.showAndWait();
if (result.isPresent() && result.get() == ButtonType.OK){
System.out.println("Ok button is pressed");
} else if(result.isPresent() && result.get() == ButtonType.CANCEL){
System.out.println("Cancel button was pressed");
}
Hope it helps. Let me know if you need any further clarification.

Categories

Resources