Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX default focused button in Alert Dialog

Since jdk 8u40, I'm using the new javafx.scene.control.Alert API to display a confirmation dialog. In the example below, "Yes" button is focused by default instead of "No" button:

public boolean showConfirmDialog(String title, String header, String content, AlertType alertType) {
    final Alert alert = new Alert(alertType);
    alert.setTitle(title);
    alert.setHeaderText(header);
    alert.setContentText(content);

    alert.getButtonTypes().clear();
    alert.getButtonTypes().addAll(ButtonType.YES, ButtonType.NO);

    final Optional<ButtonType> result = alert.showAndWait();
    return result.get() == ButtonType.YES;
}

And I don't know how to change it.

EDIT :

Here a screenshot of the result where "Yes" button is focused by default :

enter image description here

like image 479
thibault Avatar asked Apr 09 '15 09:04

thibault


3 Answers

I am not sure if the following is the way to usually do this, but you could change the default button by looking up the buttons and setting the default-behavior yourself:

public boolean showConfirmDialog(String title, String header, String content, AlertType alertType) {
    final Alert alert = new Alert(alertType);
    alert.setTitle(title);
    alert.setHeaderText(header);
    alert.setContentText(content);

    alert.getButtonTypes().clear();
    alert.getButtonTypes().addAll(ButtonType.YES, ButtonType.NO);

    //Deactivate Defaultbehavior for yes-Button:
    Button yesButton = (Button) alert.getDialogPane().lookupButton( ButtonType.YES );
    yesButton.setDefaultButton( false );

    //Activate Defaultbehavior for no-Button:
    Button noButton = (Button) alert.getDialogPane().lookupButton( ButtonType.NO );
    noButton.setDefaultButton( true );

    final Optional<ButtonType> result = alert.showAndWait();
    return result.get() == ButtonType.YES;
}
like image 101
crusam Avatar answered Nov 20 '22 22:11

crusam


A simple function thanks to crusam:

private static Alert setDefaultButton ( Alert alert, ButtonType defBtn ) {
   DialogPane pane = alert.getDialogPane();
   for ( ButtonType t : alert.getButtonTypes() )
      ( (Button) pane.lookupButton(t) ).setDefaultButton( t == defBtn );
   return alert;
}

Usage:

final Alert alert = new Alert( 
         AlertType.CONFIRMATION, "You sure?", ButtonType.YES, ButtonType.NO );
if ( setDefaultButton( alert, ButtonType.NO ).showAndWait()
         .orElse( ButtonType.NO ) == ButtonType.YES ) {
   // User selected the non-default yes button
}
like image 21
Sheepy Avatar answered Nov 20 '22 22:11

Sheepy


If you have a look at (private) ButtonBarSkin class, there is a method called doButtonOrderLayout() that performs the layout of the buttons, based in some default OS behavior.

Inside of it, you can read this:

/* now that all buttons have been placed, we need to ensure focus is set on the correct button. [...] If so, we request focus onto this default button. */

Since ButtonType.YES is the default button, it will be the one focused.

So @ymene answer is correct: you can change the default behavior and then the one focused will be NO.

Or you can just avoid using that method, by setting BUTTON_ORDER_NONE in the buttonOrderProperty(). Now the first button will have the focus, so you need to place first the NO button.

alert.getButtonTypes().setAll(ButtonType.NO, ButtonType.YES);

ButtonBar buttonBar=(ButtonBar)alert.getDialogPane().lookup(".button-bar");
buttonBar.setButtonOrder(ButtonBar.BUTTON_ORDER_NONE);

Note that YES will still have the default behavior: This means NO can be selected with the space bar (focused button), while YES will be selected if you press enter (default button).

Alert dialog

Or you can change also the default behavior following @crusam answer.

like image 4
José Pereda Avatar answered Nov 20 '22 21:11

José Pereda