【问题标题】:JavaFX - Accelerator not working when textfield has focusJavaFX - 当文本字段具有焦点时加速器不起作用
【发布时间】:2015-03-30 02:43:25
【问题描述】:

在我的应用程序中,我有一个使用加速器的屏幕。我正在使用功能键 F3 在我的应用程序中执行操作。每次都可以正常工作,但是当我单击此屏幕上的任何 TextField 时,功能键不会执行。

这是我设置加速器的代码:

    scene.getAccelerators().put(
            new KeyCodeCombination(KeyCode.F3),
            new Runnable() {
                @Override
                public void run() {
                    // do sth here
                }
            }
    );

当我单击我的文本字段然后按 F3 功能键时,它不起作用。 有人知道解决方案吗?

【问题讨论】:

  • 查看这个 SO 问题以获得不需要修改控件的更好答案:stackoverflow.com/questions/25397742/…
  • 似乎在 fx9 中已修复,也就是说,如果 textField 被聚焦,加速器(在菜单中并手动安装)正在工作

标签: java javafx javafx-8 accelerator


【解决方案1】:

如果您使用的是 JavaFx+Scene 构建器,那么只需创建一个函数,将所有事件重定向到相应的函数,然后使用 OnKeyReleased 事件将此函数添加到场景中的每个元素

【讨论】:

    【解决方案2】:

    如果您在其他位置设置了加速器,例如菜单栏,则使用其他一些解决方案将导致快捷方式被执行两次。

    在我的例子中,在我的快捷键 (SHIFT + F3) 中使用修饰符在文本区域处于焦点时有效,但在仅使用诸如 F3 之类的加速器时无效。

    我将我的设置为仅将事件处理程序用于不使用修饰符的快捷方式。

    public  static final double JAVA_VERSION = Double.parseDouble(System.getProperty("java.specification.version"));
    public static void makeInputFieldShortCutFriendly(Node node) {
        //this bug wasn't fixed until 9.0
        if (JAVA_VERSION < 9) {
            node.addEventHandler(KeyEvent.KEY_RELEASED, (KeyEvent event) -> {
                if (!event.getCode().isModifierKey()) {
                    if (!event.isAltDown() && !event.isShiftDown() && !event.isAltDown()) {
                        Runnable r = node.getScene().getAccelerators().get(new KeyCodeCombination(event.getCode(), KeyCodeCombination.SHORTCUT_ANY));
    
                        if (r != null) {
                            r.run();
                        }
                    }
                }
            });
        }
    }
    

    编辑:Java 9 中没有修复修饰符快捷方式。鉴于目前 JDK 8 的流行,我们可能应该提供一些向后的功能或要求用户将 JRE 更新到 9+。

    【讨论】:

    • 问题似乎在 fx9 中得到解决,也就是说,如果 textField 被聚焦,加速器(在菜单中并手动安装)正在工作
    【解决方案3】:

    此答案基于tikerman's。我添加了处理修饰键的代码。

    if (!event.getCode().isModifierKey()) {
        Consumer<KeyCombination.Modifier[]> runAccelerator = (modifiers) -> {
            Runnable r = getScene().getAccelerators().get(new KeyCodeCombination(event.getCode(), modifiers));
            if (r != null) {
                r.run();
            }
        };
    
        List<KeyCombination.Modifier> modifiers = new ArrayList<>();
        if (event.isControlDown()) modifiers.add(KeyCodeCombination.CONTROL_DOWN);
        if (event.isShiftDown()) modifiers.add(KeyCodeCombination.SHIFT_DOWN);
        if (event.isAltDown()) modifiers.add(KeyCodeCombination.ALT_DOWN);
    
        runAccelerator.apply(modifiers.toArray(new KeyCombination.Modifier[modifiers.size()]));
    }
    

    编辑:修复消费者拼写。

    【讨论】:

    • 这看起来很有趣,但代码正确吗? modifier 变量似乎在定义之前使用过?另外,代码的目的是什么?即使使用更简单的版本,我的带修饰符的加速器似乎也可以正常工作(使用 JavaFX 8 测试)。
    • 我对修饰符的理解是错误的——它们在其他代码中没有得到很好的处理,修饰键本身在尝试处理其释放时会引发异常。我仍然相信代码的顺序是错误的。
    • @Suma 第一个modifier 变量是一个lambda 表达式的参数。换句话说,它对于 runAccelerator 对象是本地的。它并不指代定义为List&lt;KeyCombination.Modifier&gt;。
    • 谢谢你的解释,我明白了。
    【解决方案4】:

    这适用于我使用 Java 1.8.0_45。但是,我在可编辑的 Combobox 字段中遇到了类似的问题。

    已编辑:

    经过进一步调查,它似乎也出现在文本字段中。我使用以下自定义类代替文本字段来解决它:

    public class ShortcutFriendlyTextField extends TextField{
    
        public ShortcutFriendlyTextField() {
            super();
            addEventHandler(KeyEvent.KEY_RELEASED,new EventHandler<KeyEvent>() {
    
                @Override
                public void handle(KeyEvent event) {
                    //handle shortcuts if defined
                    Runnable r=getScene().getAccelerators().get(new KeyCodeCombination(event.getCode()));
                    if(r!=null) {
                        r.run();  
                    }
                }
            }); 
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多