I made a JavaFX alert dialog box to prompt the user, asking if they want to save the output from the console before closing the application.
I have the yes and no options taken care of. If the user clicks cancel, I want it to just close the dialog box and leave everything open. As of right now, if I hit cancel it will close the GUI.
Here is my code for overriding the close button on the GUI.
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>()
{
#Override
public void handle(WindowEvent event)
{
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("Warning");
alert.setHeaderText("Would You Like To Save Your Console Output?");
alert.setContentText("Please choose an option.");
ButtonType yesButton = new ButtonType("Yes");
ButtonType noButton = new ButtonType("No");
ButtonType cancelButton = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(yesButton, noButton, cancelButton);
Optional<ButtonType> result = alert.showAndWait();
if(result.get() == yesButton)
{
Main.setConsoleVisible();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
else if(result.get() == noButton)
{
System.exit(0);
}
else if(result.get() == cancelButton)
{
}
}
});
Both in "yesButton" and "cancelButton" if-blocks consume the CloseRequest WindowEvent:
else if(result.get() == cancelButton)
{
event.consume();
}
Use Platform.exit() instead of System.exit(0).
Use primaryStage.close(); instead of System.exit(0);
From the documentation for onCloseRequest:
Called when there is an external request to close this Window. The installed event handler can prevent window closing by consuming the received event.
Be aware that result.get() will throw an exception if the user closes the alert dialog without pressing any buttons. The Dialog documentation explains this thoroughly.
Related
This question already has answers here:
Alert Box For When User Attempts to close application using setOnCloseRequest in JavaFx
(2 answers)
Closed 4 years ago.
I want to implement a dialogue alert when the user clicks the close button. With the option for yes they do want to leave and no they don't.
Button button = new Button("Exit");
gridPane.add(button, 12, 12);
button.setOnAction(e ->{
primaryStage.close();
});
How would I go about this?
Use the onCloseRequest event of the stage for closing the window using the X button of the window:
private static boolean confirmClose() {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setContentText("Do you really want to close the app?");
return alert.showAndWait().orElse(ButtonType.CANCEL) == ButtonType.OK;
}
primaryStage.setOnCloseRequest(event -> {
if (!confirmClose()) {
event.consume();
}
});
Note that this event is not triggered when closing the window programmatically. You need to request user confirmation yourself in such a case:
button.setOnAction(evt -> {
if (confirmClose()) {
primaryStage.close();
}
});
You have a pretty good article which explains et give some examples about Alert
The one you need is a Confirmation-Dialog :
button.setOnAction(e ->
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Exit Application");
alert.setHeaderText("Exit of the App");
alert.setContentText("Do you really want to exit ? ");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
primaryStage.close();
Platform.exit();
System.exit(0);
} else {
// ... user chose CANCEL or closed the dialog
}
});
Try something like:
Button button = new Button("Exit");
gridPane.add(button, 12, 12);
button.setOnAction(e ->{
if(confirmDialog(
"Sure you want to quit?",
"Sure you want to quit?",
"We're really closing - click yes to quit, no to stay in the app")
) {
primaryStage.close();
}
});
...
public boolean confirmDialog(String title, String headerText, String message) {
Alert alert = new Alert(AlertType.CONFIRMATION, message, ButtonType.YES, ButtonType.NO);
alert.initModality(Modality.APPLICATION_MODAL);
alert.initOwner(scene); //scene must be accessible as a field
alert.setTitle(title);
alert.setHeaderText(headerText);
ButtonType result = alert.showAndWait().orElse(ButtonType.NO);
return ButtonType.YES==result;
}
I am working with Swing right now and I do not get this to work properly.
What I need is the following:
I've got a class "Client" that is able to connect to a TCP server.
If the connection fails (wrong IP for example), then it will show an error dialog that can be closed by clicking on the "OK" Button.
However if the client connected successfully, a window should popup that runs until my client receives a specific message from the server.
My code looks like this:
if(ip != null) {
Client c = new Client();
try{
c.connect(ip, 56556);
JOptionPane msg = new JOptionPane("Connecting...", JOptionPane.INFORMATION_MESSAGE);
JDialog dlg = msg.createDialog("Connecting...");
dlg.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dlg.setVisible(true);
c.addIncomingMessageHandler(new IncomingMessageHandler(){
#Override
public void incomingMessage(Connection<?> cnctn, Object o) {
dlg.setVisible(false);
dlg.dispose();
}
});
}catch(Exception e) {
int n = JOptionPane.showOptionDialog(this, "Oops! Something went wrong!",
"Title", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE,
null, new Object[] {"OK"}, JOptionPane.OK_OPTION);
}
}
So the exception is throws if c.connect() fails.
c.addIncomingMessageHandler() is a listener that listens to any incoming messages to the client. If the server sends something, this method will be called. If that's the case, the JDialog will be closed. But this window can be closed right now by clicking on the OK-Button.
I'd like to rename that button and add a function.
The new text should be "Cancel" and if the button is pressed, the client should be closed (c.disconnect) and the window itself should be closed as well.
How could I do that?
From the Documentation:
Stopping Automatic Dialog Closing
By default, when the user clicks a JOptionPane-created button, the dialog closes. But what if you want to check the user's answer before closing the dialog? In this case, you must implement your own property change listener so that when the user clicks a button, the dialog does not automatically close.
DialogDemo contains two dialogs that implement a property change listener. One of these dialogs is a custom modal dialog, implemented in CustomDialog, that uses JOptionPane both to get the standard icon and to get layout assistance. The other dialog, whose code is below, uses a standard Yes/No JOptionPane. Though this dialog is rather useless as written, its code is simple enough that you can use it as a template for more complex dialogs.
Besides setting the property change listener, the following code also calls the JDialog's setDefaultCloseOperation method and implements a window listener that handles the window close attempt properly. If you do not care to be notified when the user closes the window explicitly, then ignore the bold code.
final JOptionPane optionPane = new JOptionPane(
"The only way to close this dialog is by\n"
+ "pressing one of the following buttons.\n"
+ "Do you understand?",
JOptionPane.QUESTION_MESSAGE,
JOptionPane.YES_NO_OPTION);
final JDialog dialog = new JDialog(frame,
"Click a button",
true);
dialog.setContentPane(optionPane);
dialog.setDefaultCloseOperation(
JDialog.DO_NOTHING_ON_CLOSE);
dialog.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
setLabel("Thwarted user attempt to close window.");
}
});
optionPane.addPropertyChangeListener(
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
if (dialog.isVisible()
&& (e.getSource() == optionPane)
&& (prop.equals(JOptionPane.VALUE_PROPERTY))) {
//If you were going to check something
//before closing the window, you'd do
//it here.
dialog.setVisible(false);
}
}
});
dialog.pack();
dialog.setVisible(true);
int value = ((Integer)optionPane.getValue()).intValue();
if (value == JOptionPane.YES_OPTION) {
setLabel("Good.");
} else if (value == JOptionPane.NO_OPTION) {
setLabel("Try using the window decorations "
+ "to close the non-auto-closing dialog. "
+ "You can't!");
}
Click here!
Related question.
I'm trying to display an alert dialog box when the player wins the game that I created. However, I get an exception:
java.lang.IllegalStateException: showAndWait is not allowed during animation or layout processing
I tried adding stop() in the AnimationTimer but it didn't work, still threw the same exception:
if (ball.getBall().getCenterY() == 0) {
//computer lost!
stop();
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle(null);
alert.setHeaderText(null);
alert.setContentText("Good game. You won! Click OK to exit.");
alert.showAndWait(); //exception thrown here
System.exit(0);
}
You can only call showAndWait() in an event handler, not from within an animation. This is not explicitly documented in the Alert class, though it is documented in the documentation for Stage.
Call show() instead, and use a handler for the onHidden event for the alert to invoke something when the alert is closed:
if (ball.getBall().getCenterY() == 0) {
//computer lost!
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle(null);
alert.setHeaderText(null);
alert.setContentText("Good game. You won! Click OK to exit.");
alert.setOnHidden(evt -> Platform.exit());
alert.show();
}
An alternative is to put your code into a private method and call using a method reference or lambda runnable in a Platform.runLater() call.
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle(null);
alert.setHeaderText(null);
alert.setContentText("Good game. You won! Click OK to exit.");
alert.showAndWait(); //exception thrown here
System.exit(0);
This make the dialog pop up outside of a timer cycle and should fix the problem.
I want to modify the default exit procedure in my javafx application to display a confirmation dialogue to the user. The confirmation dialogue will exit the application if the user chooses OK and will keep the application running when user chooses Cancel.
What should I do to make this in javaFX?
You can use Alert since 8.40
stage.setOnCloseRequest(evt -> {
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirm Close");
alert.setHeaderText("Close program?");
alert.showAndWait().filter(r -> r != ButtonType.OK).ifPresent(r->evt.consume());
});
primaryStage.addEventFilter(WindowEvent.WINDOW_CLOSE_REQUEST, e->{
e.consume();
Popup popup = new Popup();
HBox buttons = new HBox();
Button close = new Button("close");
Button cancel = new Button("cancel");
buttons.getChildren().addAll(close,cancel);
buttons.setPadding(new Insets(5,5,5,5));
popup.getContent().add(buttons);
popup.show(primaryStage);
close.setOnAction(ex -> {
Platform.exit();
});
cancel.setOnAction(ec -> {
popup.hide();
});
});
like the title implies i've got a problem with my application. The application is supposed to run in fullscreen mode (no intention for switching back to window mode), so i designed a footer-bar holding some images (with a Label, in a VBox) so the user could navigate or exit the program.
So after starting the application all Buttons work just fine with touch. Even the Exit-button in my footer-bar responded correctly by opening my custom Dialog. But here starts my Problem. The Dialog is shown by showAndWait()-Method call, but does not respond to Touch-Events. In contrary mouse-events are still processed (i still can use a mouse to click the Buttons in my Dialog and the Dialog is responding correctly).
I hope someone got an idea what i'm doing wrong.
MyDialog.java:
public static boolean showExitDialog(Window owner, ResourceBundle resources) {
LOGGER.info("Showing exit dialog...");
final Dialog<ButtonType> dialog = new Dialog<ButtonType>();
dialog.getDialogPane().getStylesheets().add(MyDialog.getInstace().getCssPath());
dialog.setContentText(resources.getString("label.exitdialog.text"));
dialog.setHeaderText(resources.getString("label.exitdialog.header"));
dialog.initOwner(owner);
dialog.initStyle(StageStyle.TRANSPARENT);
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.getDialogPane().getButtonTypes().add(new ButtonType(resources.getString("btn.Exitdialog.exit"), ButtonData.OK_DONE););
dialog.getDialogPane().getButtonTypes().add(new ButtonType(resources.getString("btn.Exitdialog.cancel"), ButtonData.FINISH));
Optional<ButtonType> result = dialog.showAndWait();
LOGGER.debug("Result: {}", result.get());
if(result.isPresent() && result.get().getButtonData() == ButtonData.OK_DONE) {
LOGGER.info("Closing exit dialog returning true...");
return true;
} else {
LOGGER.info("Closing exit dialog returning false...");
return false;
}
}
In MainApp.java:
private EventHandler<WindowEvent> confirmCloseEventHandler = event -> {
// close event handling logic.
// consume the event if you wish to cancel the close operation.
if(MyDialog.showExitDialog(primaryStage, rb)) {
event.consume();
System.exit(0);
}
};
...
primaryStage.setOnCloseRequest(confirmCloseEventHandler);
In FooterBar.java:
#FXML
private void exitProgramPressedTouch(TouchEvent event) {
event.consume();
controller.getWindow().fireEvent(new WindowEvent(controller.getWindow(), WindowEvent.WINDOW_CLOSE_REQUEST));
}
*Edit* Oh totally forgot: No Exception or anything else is thrown.
I don't know the reason for the described behavior - maybe a bug. However, you could try to listen for ActionEvent instead of TouchEvent. It handles both touch and mouse events:
#FXML
private void exitProgramPressedTouch(ActionEvent event) {
event.consume();
controller.getWindow().fireEvent(new WindowEvent(controller.getWindow(), WindowEvent.WINDOW_CLOSE_REQUEST));
}
Maybe you need also to change the attribute which binds the event listener (from onTouch to onAction) in your FXML file.
Finally, I think, you could avoid System.exit(0); if you consume the close event only when the cancel button has been clicked:
if(!MyDialog.showExitDialog(primaryStage)) {
event.consume();
}