Javafx: Close alert box (or, any dialog box) programatically

24.3k views Asked by At

I have a JavaFx application in which I display an alert box using:

alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Title");
alert.setHeaderText("Some Text");
alert.setContentText("Choose your option.");
buttonTypeOne = new ButtonType("Yes");
buttonTypeCancel = new ButtonType("No", ButtonData.CANCEL_CLOSE);
alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeCancel);
Optional<ButtonType> result = alert.showAndWait();

Because the alert executesshowAndWait, so it will be displayed till the user either presses 'Yes' or 'No' or 'Close' the dialog.

Problem: I need to close this dialog programatically from somewhere else. To elaborate, if, let's say the user does not chose any option for 20 sec, or let's say this alert box was shown for some background process which just got over, and now I wish to close this alert box by setting result to be buttonTypeCancel, instead of the user pressing any button. (Like dispose method in Swing)

How can I do this? I tried Event.fireevent (https://stackoverflow.com/a/22459308/3155986) but I am not able to write the correct event associated.

Thanks in advance!

Edit: Including sample code-

  1. MainApp.java - Java class responsible for handling the application
  2. Controller.java - Corresponding controller file
  3. Design.fxml - FXML file for the application which is loaded via MainApp.java and controlled by Controller.java
  4. Compute.java - Another java class to perform computations.

    public class Compute{ Alert alert;

    public void function1{
      Platform.runLater(new Runnable(){
          public void run(){
          alert = new Alert(AlertType.CONFIRMATION);
          alert.setTitle("Title");
          alert.setHeaderText("Some Text");
          alert.setContentText("Choose your option.");
          buttonTypeOne = new ButtonType("Yes");
          buttonTypeCancel = new ButtonType("No", ButtonData.CANCEL_CLOSE);
          alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeCancel);
    
          Optional<ButtonType> result = alert.showAndWait();
          if (result.get() == buttonTypeOne){
          // ... user chose "One"
          } else {
          // ... user chose CANCEL or closed the dialog
          }
    
          }
      });
    }
    
    public void function2{
     //......Does some long computation here 
     //.... If the computation finishes before the user chooses 'Yes' or 'No' on alert box
    //...Then close the alertbox here and execute the code corresponding to buttonTypeCancel
    
    
    //..I tried alert.close(); and alert.hide(); but doesn't work.
    }
    

    }

Also, is there any alternate solution to do this? Originally, I wanted to keep the Compute.java clean of any javafx code but couldn't figure out how.

3

There are 3 answers

13
Uluk Biy On BEST ANSWER

Try this

public void function2 {
    Button cancelButton = ( Button ) alert.getDialogPane().lookupButton( buttonTypeCancel );
    cancelButton.fire();
}

Or for more general

public void function2 {
    for ( ButtonType bt : alert.getDialogPane().getButtonTypes() )
    {
        if ( bt.getButtonData() == ButtonBar.ButtonData.CANCEL_CLOSE )
        {
            Button cancelButton = ( Button ) alert.getDialogPane().lookupButton( bt );
            cancelButton.fire();
            break;
        }
    }
}

Full example:

@Override
public void start( final Stage primaryStage )
{
    Alert alert = new Alert( Alert.AlertType.CONFIRMATION );
    alert.setTitle( "Title" );
    alert.setHeaderText( "Some Text" );
    alert.setContentText( "Choose your option." );
    ButtonType buttonTypeOne = new ButtonType( "Yes" );
    alert.initModality( Modality.NONE );
    ButtonType buttonTypeCancel = new ButtonType( "No", ButtonBar.ButtonData.CANCEL_CLOSE );
    alert.getButtonTypes().setAll( buttonTypeOne, buttonTypeCancel );

    Button b = new Button( "close alert" );
    b.setOnAction(( ActionEvent event ) ->
    {
        for ( ButtonType bt : alert.getDialogPane().getButtonTypes() )
        {
            System.out.println( "bt = " + bt );
            if ( bt.getButtonData() == ButtonBar.ButtonData.CANCEL_CLOSE )
            {
                Button cancelButton = ( Button ) alert.getDialogPane().lookupButton( bt );
                cancelButton.fire();
                break;
            }
        }
    });

    final Scene scene = new Scene( new Group( b ), 400, 300 );
    primaryStage.setScene( scene );
    primaryStage.show();

    Optional<ButtonType> result = alert.showAndWait();
    if ( result.get() == buttonTypeOne )
    {
        System.out.println( "one " );
    }
    else if( result.get() == buttonTypeCancel )
    {
        System.out.println( "cancel " );
    }
}
3
ItachiUchiha On

You can invoke close() method on the Alert or any Dialog.

Here is a simple example which waits for 5 secs, and if the Alert is still showing, it closes it.

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;
import javafx.stage.Stage;

import java.util.Optional;

public class Main extends Application{

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setTitle("Title");
        alert.setHeaderText("Some Text");
        alert.setContentText("Choose your option.");
        ButtonType buttonTypeOne = new ButtonType("Yes");
        ButtonType buttonTypeCancel = new ButtonType("No", ButtonBar.ButtonData.CANCEL_CLOSE);
        alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeCancel);

        Thread thread = new Thread(() -> {
            try {
                // Wait for 5 secs
                Thread.sleep(5000);
                if (alert.isShowing()) {
                    Platform.runLater(() -> alert.close());
                }
            } catch (Exception exp) {
                exp.printStackTrace();
            }
        });
        thread.setDaemon(true);
        thread.start();
        Optional<ButtonType> result = alert.showAndWait();
    }
}
0
Gulu Bulu On

It's closing opened dialog in 2 second.

dialog = new Dialog<>();
dialog.setTitle("It's a dialog!");
dialog.show();

    Thread newThread = new Thread(new Runnable() {
    @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }

            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    dialog.close();
                }
                });
            }
    });
    newThread.start();