JavaFX 警报对话框忽略焦点按钮
JavaFX alert dialog ignores the focused button
为什么 JavaFX 警告对话框会触发 Platform.exit();当我按下 Enter 键时,即使警报对话框中的焦点按钮是取消?
soaStage.setOnCloseRequest(new EventHandler<WindowEvent>()
{
@Override
public void handle(WindowEvent event)
{
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Confirm");
alert.setHeaderText("Are you sure you want to exit?");
alert.setContentText("Press OK to exit, or Cancel to stay.");
alert.initOwner(soaStage);
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK)
{
Platform.exit();
}
else
{
event.consume();
}
}
});
默认按钮在 enter
时触发
当您按下 enter 时会触发确定按钮,因为它是 default button.
A default Button is the button that receives a keyboard VK_ENTER press, if no other node in the scene consumes it.
在默认的 JavaFX 8 Modena 样式表中,默认按钮用蓝色表示,而不是标准按钮的灰色。
如何删除默认按钮行为
您可以通过不将“确定”按钮设为默认按钮来从警告对话框中删除此行为:
Button okButton = (Button) alert.getDialogPane().lookupButton(ButtonType.OK);
okButton.setDefaultButton(false);
我建议您不要这样做,而是始终在警报对话框中保留一个默认按钮。
在 OS X 上,标准警报类型对话框有一个默认按钮,它由 enter 触发,即使另一个按钮被聚焦,所以 JavaFX 中的标准行为是与此一致。注意:要在 OS X 的默认对话框中允许此行为,必须 enable full keyboard access.
如果您确实将“确定”按钮更改为不是默认按钮,我建议您将其文本更改为其他内容(例如,退出您的案例):
okButton.setText("Exit");
如何制作 enter 聚焦按钮
现在,如果您还想在按下 enter 时触发焦点按钮,那么您可以这样做:
EventHandler<KeyEvent> fireOnEnter = event -> {
if (KeyCode.ENTER.equals(event.getCode())
&& event.getTarget() instanceof Button) {
((Button) event.getTarget()).fire();
}
};
DialogPane dialogPane = alert.getDialogPane();
dialogPane.getButtonTypes().stream()
.map(dialogPane::lookupButton)
.forEach(button ->
button.addEventHandler(
KeyEvent.KEY_PRESSED,
fireOnEnter
)
);
注意:在任何情况下,当您按下 space.
时,焦点按钮总是被激活
我们可以通过创建需要在应用程序启动时实例化一次的 class 将 ENTER 绑定添加到整个按钮。
public class EnableButtonEnterKey extends ButtonBehavior<Button> {
public EnableButtonEnterKey() {
super(new Button());
BUTTON_BINDINGS.add(new KeyBinding(ENTER, KEY_PRESSED, "Press"));
BUTTON_BINDINGS.add(new KeyBinding(ENTER, KEY_RELEASED, "Release"));
}
}
启动应用程序时,调用
new EnableButtonEnterKey();
就是这样。
为什么 JavaFX 警告对话框会触发 Platform.exit();当我按下 Enter 键时,即使警报对话框中的焦点按钮是取消?
soaStage.setOnCloseRequest(new EventHandler<WindowEvent>()
{
@Override
public void handle(WindowEvent event)
{
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Confirm");
alert.setHeaderText("Are you sure you want to exit?");
alert.setContentText("Press OK to exit, or Cancel to stay.");
alert.initOwner(soaStage);
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK)
{
Platform.exit();
}
else
{
event.consume();
}
}
});
默认按钮在 enter
时触发当您按下 enter 时会触发确定按钮,因为它是 default button.
A default Button is the button that receives a keyboard VK_ENTER press, if no other node in the scene consumes it.
在默认的 JavaFX 8 Modena 样式表中,默认按钮用蓝色表示,而不是标准按钮的灰色。
如何删除默认按钮行为
您可以通过不将“确定”按钮设为默认按钮来从警告对话框中删除此行为:
Button okButton = (Button) alert.getDialogPane().lookupButton(ButtonType.OK);
okButton.setDefaultButton(false);
我建议您不要这样做,而是始终在警报对话框中保留一个默认按钮。
在 OS X 上,标准警报类型对话框有一个默认按钮,它由 enter 触发,即使另一个按钮被聚焦,所以 JavaFX 中的标准行为是与此一致。注意:要在 OS X 的默认对话框中允许此行为,必须 enable full keyboard access.
如果您确实将“确定”按钮更改为不是默认按钮,我建议您将其文本更改为其他内容(例如,退出您的案例):
okButton.setText("Exit");
如何制作 enter 聚焦按钮
现在,如果您还想在按下 enter 时触发焦点按钮,那么您可以这样做:
EventHandler<KeyEvent> fireOnEnter = event -> {
if (KeyCode.ENTER.equals(event.getCode())
&& event.getTarget() instanceof Button) {
((Button) event.getTarget()).fire();
}
};
DialogPane dialogPane = alert.getDialogPane();
dialogPane.getButtonTypes().stream()
.map(dialogPane::lookupButton)
.forEach(button ->
button.addEventHandler(
KeyEvent.KEY_PRESSED,
fireOnEnter
)
);
注意:在任何情况下,当您按下 space.
时,焦点按钮总是被激活我们可以通过创建需要在应用程序启动时实例化一次的 class 将 ENTER 绑定添加到整个按钮。
public class EnableButtonEnterKey extends ButtonBehavior<Button> {
public EnableButtonEnterKey() {
super(new Button());
BUTTON_BINDINGS.add(new KeyBinding(ENTER, KEY_PRESSED, "Press"));
BUTTON_BINDINGS.add(new KeyBinding(ENTER, KEY_RELEASED, "Release"));
}
}
启动应用程序时,调用
new EnableButtonEnterKey();
就是这样。