关键事件有三种:
KEY_PRESSED
,则,
KEY_TYPED
和
KEY_RELEASED
。在按键笔划中,每种类型的事件都会按顺序激发到事件发生时具有键盘焦点的UI节点。
A.
TextField
具有内部侦听器
键入KEY\u
事件;所以如果
键入KEY\u
事件发生在文本字段具有焦点、在文本字段中输入字符(或发生其他操作,例如删除字符或移动插入符号,具体取决于键)时。
在您的代码中,您将侦听其中的第一个-
按键\u已按下
-发生在按钮上。如果按键的代码为
A
,您消费
那个
事件(the
按键\u已按下
事件),然后将键盘焦点转移到文本字段。稍后,用户释放键,由于文本字段现在具有焦点,因此
键入KEY\u
事件在文本字段上激发。请注意,这是一个新事件,因此它不会被使用,因此文本字段的反应就像输入了字符一样。最后,a
KEY\u已释放
事件在文本字段上激发。
如果添加调试代码,则可以看到此操作:
txt2.addEventFilter(KeyEvent.ANY, e -> {
System.out.printf("Key event on text field: type=%s, code=%s, character=%s%n",
e.getEventType(), e.getCode(), e.getCharacter());
});
要解决此问题,只需侦听一系列事件中的最后一个事件:key released事件。请注意,您不需要使用该事件。
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
StackPane root = new StackPane();
TextField txt1 = new TextField();
TextField txt2 = new TextField();
VBox vbox = new VBox();
vbox.getChildren().add(btn);
vbox.getChildren().add(txt1);
vbox.getChildren().add(txt2);
root.getChildren().add(vbox);
Scene scene = new Scene(root, 300, 250);
btn.setOnKeyReleased((KeyEvent e) ->{
if (e.getCode() == KeyCode.A) {
txt2.requestFocus();
}
});
txt2.addEventFilter(KeyEvent.ANY, e -> {
System.out.printf("Key event on text field: type=%s, code=%s, character=%s%n",
e.getEventType(), e.getCode(), e.getCharacter());
});
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
btn.requestFocus();
}