令人费解的小写字母 KeyEvent 处理
Puzzling KeyEvent handling for lowercase letters
如果我如下设置 KeyEvent
处理程序,对于大写字母和非字母或数字的 Ascii 字符,行为如我所料,并且正如 Oracle 文档似乎指定的那样。
但是,对于小写字母,如果我在输入字母时按住 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$
您使用了错误的事件类型来获得您想要的行为。
阅读 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.valueOf 方法是如何用于构造组合键的。还要注意(标识字符的“4”除外)每个键如何由其键码标识。如,在我的键盘上,小写q和大写Q是同一个键,只是用了一个shift来生成大写键,那么Ctrl+q编码为Ctrl+Q,Ctrl+Q编码为Ctrl+Shift+问。另外,我的键盘没有美元键,而是通过按 shift 键和四键生成美元。通常四键代码是 DIGIT4,但出于某种原因,这在这种情况下不起作用。因此,为了获得 Ctrl+$ 操作,我使用 Ctrl+Shift+'4' 来表示按下生成字符“4”的键时的控制和移位修饰符。
评论一下你原样的操作
此外,作为主要是琐事的旁注,在 Mac (2012 MacBook Air OS X 10.11.4, Java 8u60 上进行测试时),您的程序给出不同的输出,可能是由于不同的键盘系统或 OS 对按键事件的处理。建议的键序列在 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
如果我如下设置 KeyEvent
处理程序,对于大写字母和非字母或数字的 Ascii 字符,行为如我所料,并且正如 Oracle 文档似乎指定的那样。
但是,对于小写字母,如果我在输入字母时按住 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$
您使用了错误的事件类型来获得您想要的行为。
阅读 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.valueOf 方法是如何用于构造组合键的。还要注意(标识字符的“4”除外)每个键如何由其键码标识。如,在我的键盘上,小写q和大写Q是同一个键,只是用了一个shift来生成大写键,那么Ctrl+q编码为Ctrl+Q,Ctrl+Q编码为Ctrl+Shift+问。另外,我的键盘没有美元键,而是通过按 shift 键和四键生成美元。通常四键代码是 DIGIT4,但出于某种原因,这在这种情况下不起作用。因此,为了获得 Ctrl+$ 操作,我使用 Ctrl+Shift+'4' 来表示按下生成字符“4”的键时的控制和移位修饰符。
评论一下你原样的操作
此外,作为主要是琐事的旁注,在 Mac (2012 MacBook Air OS X 10.11.4, Java 8u60 上进行测试时),您的程序给出不同的输出,可能是由于不同的键盘系统或 OS 对按键事件的处理。建议的键序列在 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