警告对话框中的 JavaFX 默认聚焦按钮

JavaFX default focused button in Alert Dialog

自 jdk 8u40 以来,我正在使用新的 javafx.scene.control.Alert API 来显示确认对话框。在下面的示例中,"Yes" 按钮默认聚焦而不是 "No" 按钮:

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;
}

而且我不知道如何更改它。

编辑:

这里是 "Yes" 按钮默认聚焦的结果截图:

我不确定以下是否是通常执行此操作的方法,但您可以通过查找按钮并自行设置默认行为来更改默认按钮:

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;
}

如果你看一下 (private) ButtonBarSkin class,有一个名为 doButtonOrderLayout() 的方法执行按钮的布局,基于一些默认值 OS 行为。

在里面,你可以读到:

/* 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. */

由于 ButtonType.YES 是默认按钮,它将成为焦点。

所以@ymene 的回答是正确的:您可以更改默认行为,然后焦点将是 NO

或者您可以通过在 buttonOrderProperty() 中设置 BUTTON_ORDER_NONE 来避免使用该方法。现在第一个按钮将获得焦点,因此您需要先放置 NO 按钮。

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

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

请注意 YES 仍将具有默认行为:这意味着 NO 可以使用 space 栏(聚焦按钮)进行选择,而 YES 将是如果按回车键(默认按钮),则选中。

或者您也可以更改@crusam 回答后的默认行为。

感谢 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;
}

用法:

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
}