JavaFx 11 ListView 即使不处于编辑状态也会消耗 ESCAPE 键按下事件

标签 javafx javafx-11

我的 JavaFx ListView 组件有问题。我在 VBox 内使用带有 TextField 和 ListView 的弹出窗口。当 TextField 处于焦点时,我通常可以按键盘上的 Esc 键关闭此弹出窗口,但是当 ListView 项目处于焦点时,弹出窗口保持打开状态,什么也不会发生。

最小可重现示例:

package sample;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

   @Override
   public void start(Stage primaryStage) throws Exception {
      MenuItem rightClickItem = new MenuItem("CLICK!");
      rightClickItem.setOnAction(a -> showdialog());
      ContextMenu menu = new ContextMenu(rightClickItem);

      Label text = new Label("Right Click on me");

      text.setContextMenu(menu);

      StackPane root = new StackPane(text);
      Scene scene = new Scene(root, 300, 250);

      primaryStage.setTitle("RightClick MenuItem And Dialog");
      primaryStage.setScene(scene);
      primaryStage.show();
   }

   private void showdialog() {
      Dialog<ButtonType> dialog = new Dialog<>();
      dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
      VBox vBox = new VBox();
      ListView listView = new ListView();
      listView.getItems().add("Item 1");
      listView.getItems().add("Item 2");
      vBox.getChildren().add(new TextField());
      vBox.getChildren().add(listView);

      vBox.addEventHandler(KeyEvent.KEY_PRESSED, keyEvent -> System.err.println("Key pressed: " + keyEvent.getCode()));

      dialog.getDialogPane().setContent(vBox);

      dialog.showAndWait();
   }


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

在我看来,Esc 键在 ListView 中被使用,这会导致关闭弹出窗口时出现问题。

顺便提一下,我使用的是 zulu-11.0.8 JDKFx 版本。

最佳答案

It seems to me that Esc key is consumed in ListView, and this cause a problem with closing a popup.

这确实是问题 - 发生在所有具有通过其各自的行为添加的消费 KeyMapping 到 ESCAPE 的控件(例如,也适用于带有 TextFormatter 的 TextField)。

没有干净的方法来干扰它(Behavior 和 InputMap 尚未进入公共(public) api)。破解的方法是从Behavior 的inputMap 中删除KeyMapping。注意:必须允许你变脏,即使用内部 api 并使用反射!

步骤:

  • 抓取控件的皮肤(将控件添加到场景图中后可用)
  • 反射(reflection)性地访问皮肤的行为
  • 从行为的 inputMap 中删除 keyMapping

示例代码片段:

private void tweakInputMap(ListView listView) {
    ListViewSkin<?> skin = (ListViewSkin<?>) listView.getSkin();
    // use your favorite utility method to reflectively access the private field
    ListViewBehavior<?> listBehavior = (ListViewBehavior<?>) FXUtils.invokeGetFieldValue(
            ListViewSkin.class, skin, "behavior");
    InputMap<?> map = listBehavior.getInputMap();
    Optional<Mapping<?>> mapping = map.lookupMapping(new KeyBinding(KeyCode.ESCAPE));
    map.getMappings().remove(mapping.get());
}

它的用法:

listView.skinProperty().addListener(ov -> {
    tweakInputMap(listView);
});

关于JavaFx 11 ListView 即使不处于编辑状态也会消耗 ESCAPE 键按下事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64264605/

相关文章:

javafx Tableview 按日期排序

java - IntelliJ IDEA 15 Scene Builder 未显示所有控件

java - 不推荐使用controlsfx 对话框是为了什么?

java - 如何修复jvm选项在gradle idea上将javafx 11导出到com.jfoenix?

java - 如何在 Eclipse 中使用 JavaFX 11?

java - 我想要可以在 Windows、Mac 和 Linux 中打开“打开方式”对话框的 java 程序?

css - 使用 CSS -fx-shape 绘制区域。怎么可能?

java - Java模块协助: Module 'name' reads package 'javafx.beans'

JavaFX、OS X、: es2, sw 的图形设备初始化失败

java - JavaFX 从 jdk 中移除后是否跨平台?