在 JavaFX 中关闭时未消耗 Dialog 上的 KeyEvent
KeyEvent on Dialog not consumed when closing in JavaFX
我需要在用户按下 ENTER 键时导航 table。为此,我创建了一个类似于以下内容的事件过滤器:
private EventHandler<KeyEvent> keyReleasedFilter = event -> {
if ((event.getCode() == KeyCode.ENTER || event.getCode() == KeyCode.TAB)) {
previousPosition = table.getFocusModel().getFocusedCell();
//do my navigation
}
}
我 运行 遇到一个问题,在 table 导航期间使用 JavaFX 模态对话框指示错误,导致此过滤器出现问题。如果用户使用 ENTER 键关闭对话框,则该事件将被我在父阶段的事件过滤器捕获。我不确定如何防止这种情况。它导致导航不一致。
这是一个演示行为的简单应用程序:
public void start(Stage primaryStage) {
final Alert d = new Alert(Alert.AlertType.ERROR);
d.initModality(Modality.WINDOW_MODAL);
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.addEventFilter(KeyEvent.KEY_RELEASED, event -> {
if ((event.getCode() == KeyCode.ENTER || event.getCode() == KeyCode.TAB)) {
d.showAndWait();
}
});
Scene scene = new Scene(new StackPane(btn), 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
我注意到对话框随 KEY_PRESSED 事件关闭,不会捕获 KEY_RELEASED 事件。
我已经尝试将事件过滤器添加到对话框(Button/DialogPane/Scene 甚至舞台)- none 拦截 KEY_RELEASED 事件。
谢谢。
所以我有一个有效的 hack - 我真的不喜欢它,所以我希望有一个更好的解决方案(一个干净的解决方案)来解决这个问题....
基本上,在我打开我的对话框之前,我设置了一个布尔值,所以我知道它是打开的。然后在我的事件过滤器中,如果设置为 true,则踢出。
public class EventTester 扩展应用程序{
public static void main(String[] args){
launch(args);
}
private boolean modalWasShowing = false;
@Override
public void start(Stage primaryStage) {
final Alert d = new Alert(Alert.AlertType.ERROR);
d.initModality(Modality.WINDOW_MODAL);
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.addEventFilter(KeyEvent.KEY_RELEASED, event -> {
if(modalWasShowing){
modalWasShowing=false;
return;
}
if ((event.getCode() == KeyCode.ENTER || event.getCode() == KeyCode.TAB)) {
modalWasShowing = true;
d.showAndWait();
}
});
Scene scene = new Scene(new StackPane(btn), 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
如果您知道更好的处理方法,请告诉我。
除非有其他原因使用 KEY_RELEASED
事件,否则我建议切换到 KEY_PRESSED
触发以进行导航,并将 EventFilter
切换到 EventHandler
.下面的示例将允许您打开和关闭 Alert
。当它打开时,您会注意到按钮文本没有改变。当它关闭时,按钮文本将改变。看看 JavaFX 如何构建事件链 here 如果您还没有看过的话。
boolean error = false;
int i = 0;
@Override
public void start(Stage primaryStage)
{
final Alert d = new Alert(Alert.AlertType.ERROR);
d.initModality(Modality.WINDOW_MODAL);
Button err = new Button();
err.setText("Error off");
err.addEventHandler(ActionEvent.ACTION, t ->
{
error = !error;
if (error)
err.setText("Error on");
else
err.setText("Error off");
});
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.addEventHandler(KeyEvent.KEY_PRESSED, event ->
{
if ((event.getCode() == KeyCode.ENTER || event.getCode() == KeyCode.TAB)) {
if (error)
{
d.showAndWait();
}
else
{
i++;
btn.setText(String.valueOf(i));
}
}
});
Scene scene = new Scene(new VBox(btn, err), 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
我需要在用户按下 ENTER 键时导航 table。为此,我创建了一个类似于以下内容的事件过滤器:
private EventHandler<KeyEvent> keyReleasedFilter = event -> {
if ((event.getCode() == KeyCode.ENTER || event.getCode() == KeyCode.TAB)) {
previousPosition = table.getFocusModel().getFocusedCell();
//do my navigation
}
}
我 运行 遇到一个问题,在 table 导航期间使用 JavaFX 模态对话框指示错误,导致此过滤器出现问题。如果用户使用 ENTER 键关闭对话框,则该事件将被我在父阶段的事件过滤器捕获。我不确定如何防止这种情况。它导致导航不一致。
这是一个演示行为的简单应用程序:
public void start(Stage primaryStage) {
final Alert d = new Alert(Alert.AlertType.ERROR);
d.initModality(Modality.WINDOW_MODAL);
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.addEventFilter(KeyEvent.KEY_RELEASED, event -> {
if ((event.getCode() == KeyCode.ENTER || event.getCode() == KeyCode.TAB)) {
d.showAndWait();
}
});
Scene scene = new Scene(new StackPane(btn), 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
我注意到对话框随 KEY_PRESSED 事件关闭,不会捕获 KEY_RELEASED 事件。
我已经尝试将事件过滤器添加到对话框(Button/DialogPane/Scene 甚至舞台)- none 拦截 KEY_RELEASED 事件。
谢谢。
所以我有一个有效的 hack - 我真的不喜欢它,所以我希望有一个更好的解决方案(一个干净的解决方案)来解决这个问题....
基本上,在我打开我的对话框之前,我设置了一个布尔值,所以我知道它是打开的。然后在我的事件过滤器中,如果设置为 true,则踢出。
public class EventTester 扩展应用程序{
public static void main(String[] args){
launch(args);
}
private boolean modalWasShowing = false;
@Override
public void start(Stage primaryStage) {
final Alert d = new Alert(Alert.AlertType.ERROR);
d.initModality(Modality.WINDOW_MODAL);
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.addEventFilter(KeyEvent.KEY_RELEASED, event -> {
if(modalWasShowing){
modalWasShowing=false;
return;
}
if ((event.getCode() == KeyCode.ENTER || event.getCode() == KeyCode.TAB)) {
modalWasShowing = true;
d.showAndWait();
}
});
Scene scene = new Scene(new StackPane(btn), 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
如果您知道更好的处理方法,请告诉我。
除非有其他原因使用 KEY_RELEASED
事件,否则我建议切换到 KEY_PRESSED
触发以进行导航,并将 EventFilter
切换到 EventHandler
.下面的示例将允许您打开和关闭 Alert
。当它打开时,您会注意到按钮文本没有改变。当它关闭时,按钮文本将改变。看看 JavaFX 如何构建事件链 here 如果您还没有看过的话。
boolean error = false;
int i = 0;
@Override
public void start(Stage primaryStage)
{
final Alert d = new Alert(Alert.AlertType.ERROR);
d.initModality(Modality.WINDOW_MODAL);
Button err = new Button();
err.setText("Error off");
err.addEventHandler(ActionEvent.ACTION, t ->
{
error = !error;
if (error)
err.setText("Error on");
else
err.setText("Error off");
});
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.addEventHandler(KeyEvent.KEY_PRESSED, event ->
{
if ((event.getCode() == KeyCode.ENTER || event.getCode() == KeyCode.TAB)) {
if (error)
{
d.showAndWait();
}
else
{
i++;
btn.setText(String.valueOf(i));
}
}
});
Scene scene = new Scene(new VBox(btn, err), 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}