令人困惑的KeyEvent处理小写字母

时间:2016-05-28 03:28:32

标签: javafx keyevent

如果我按如下所示设置KeyEvent处理程序,则行为如我所料,并且正如Oracle文档似乎指定的那样,对于大写字母和非字母或数字的Ascii字符。

但是,对于小写字母,如果我在键入字母时按住Ctrl键,则EventHandler似乎无法注册按键。

下面的输出显示了这一点,输入Q,q,$,Ctrl + Q,Ctrl + q,Ctrl + $。

任何人都可以阐明这种行为吗?我错过了什么吗?我搜索过但没有找到任何其他对此问题的引用。

import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.event.*;
import javafx.scene.input.KeyEvent;

// Test handling keypresses of upper and lower case letter, and non-alphameric ascii symbol,
// to see if any difference exists when Ctrl is held down
// between the handling for (ev.isShortcutDown()) and (ev.isMetaDown() || ev.isControlDown())
// and between the three character types

// Program to be tested by typing, in sequence,
//              Q  q  $  Ctrl+Q  Ctrl+q  Ctrl+$


public class TestHandlingKeyEvents extends Application {

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

    public void start(Stage stage) throws Exception {
        Scene scene = new Scene(new Group());
        stage.setScene(scene);

        EventHandler<KeyEvent> handleUserTyping = ev -> {

            String charTyped = ev.getCharacter();
            switch (charTyped) {
                case "Q":               // quit
                    System.out.println("\nQ typed ");
                    if (ev.isShortcutDown()) 
                        System.out.println("with Shortcut down ");
                    if (ev.isMetaDown() || ev.isControlDown())
                        System.out.println("with Meta or Ctrl down ");
                    break;                  
                case "q":               // complete reset
                    System.out.println("\nq typed ");
                    if (ev.isShortcutDown()) 
                        System.out.println("with Shortcut down ");
                    if (ev.isMetaDown() || ev.isControlDown())
                        System.out.println("with Meta or Ctrl down ");              
                    break;
                case "$":               // back to last view
                    System.out.println("\n$ typed ");
                    if (ev.isShortcutDown()) 
                        System.out.println("with Shortcut down ");
                    if (ev.isMetaDown() || ev.isControlDown())
                        System.out.println("with Meta or Ctrl down ");              
                    break;
            }
        };

        scene.setOnKeyTyped(handleUserTyping);
        stage.show();
    }
}

输出:

john@jlaptop2:/java$ java TestHandlingKeyEvents

Q typed 

q typed 

$ typed 

Q typed 
with Shortcut down 
with Meta or Ctrl down 

$ typed 
with Shortcut down 
with Meta or Ctrl down 
john@jlaptop2:/java$ 

1 个答案:

答案 0 :(得分:1)

您使用了错误类型的事件来获得您想要的行为。

阅读KeyEvent javadoc中的各种类型的KeyEvent。

基本上,您可以在KEY_PRESSED事件而不是KEY_TYPED事件上注册事件处理程序。只有在底层系统注册通过键入生成的unicode字符时才会生成键类型事件,而对于您尝试捕获的某些键输入序列则不是这种情况。为了捕获更多与unicode字符生成无关的输入字符序列,需要使用较低级别的KEY_PRESSED(或KEY_RELEASED)事件。

但是,您可以使用更高级别的界面,并且可能更适合您的用例,即根据KeyCodeCombinations设置加速器。

使用加速器的示例

import javafx.application.Application;
import javafx.collections.ObservableMap;
import javafx.scene.*;
import javafx.scene.input.KeyCombination;
import javafx.stage.Stage;

// Test handling keypresses of upper and lower case letter, 
// and non-alphameric ascii symbol.    
// Program to be tested by typing, in sequence,
//              Ctrl+Q  Ctrl+q  Ctrl+$    
public class TestHandlingKeyAccelerators extends Application {    
    public void start(Stage stage) throws Exception {
        Scene scene = new Scene(new Group());
        stage.setScene(scene);

        ObservableMap<KeyCombination, Runnable> accelerators = 
                scene.getAccelerators();

        accelerators.put(
                KeyCombination.valueOf("Ctrl+Q"), 
                () -> System.out.println("Ctrl+q -> reset")
        );
        accelerators.put(
                KeyCombination.valueOf("Ctrl+Shift+Q"), 
                () -> System.out.println("Ctrl+Q -> quit")
        );
        accelerators.put(
                KeyCombination.valueOf("Ctrl+Shift+'4'"), 
                () -> System.out.println("Ctrl+$ -> back to last view")
        );

        stage.show();
    }

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

注意KeyCombination.valueO f方法如何用于构造组合键。另请注意(每个键标识一个字符的除外)每个键都由其键码标识。因为,在我的键盘上,小写q和大写Q是相同的键,但是使用shift来生成大写键,然后Ctrl + q编码为Ctrl + Q,Ctrl + Q编码为Ctrl + Shift + Q.此外,我的键盘没有美元键,而是通过按shift和四键生成一美元。通常四个关键代码是DIGIT4,但由于某种原因,在这种情况下这不起作用。因此,为了获得Ctrl + $操作,我使用Ctrl + Shift +&#39; 4&#39;表示控制和移位修饰符,用于生成字符“4”的键。被压了。

评论原始样本的操作

此外,作为一个主要是琐事的旁注,在Mac(2012 MacBook Air OS X 10.11.4,Java 8u60)上进行测试时,您的程序会提供不同的输出,可能是由于不同的键盘系统或操作系统处理关键事件。 Mac上输出的建议密钥序列为:

Q typed 

q typed 

$ typed 

您在问题中显示的以下输出序列不会在Mac上生成:

Q typed 
with Shortcut down 
with Meta or Ctrl down 

$ typed 
with Shortcut down 
with Meta or Ctrl down