JavaFX TextField 如何防止在按键事件中键入键
JavaFX TextField how to prevent key from getting typed in keypressed event
我需要检测数字小键盘的按键操作才能做一些事情。这是代码:
textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if(event.getCode().isKeypadKey()) {
//do stuff here...
event.consume();
}
}
});
假设用户在小键盘上按下“2”,虽然事件被消耗,字符“2”将出现在文本字段中。但我不想要那个。有什么想法可以防止这种情况发生吗?
更有趣的是,如果我抛出一个虚拟异常而不是使用事件,它将阻止键类型化事件。
您面临的问题可以通过添加日志监听器来解释:
textField.addEventFilter(Event.ANY, e -> System.out.println(e));
因此,当您键入一个键时,您会得到:
KeyEvent [source = TextField@42924cd[styleClass=text-input text-field], target = TextField@42924cd[styleClass=text-input text-field], eventType = KEY_PRESSED, consumed = false, character = , text = 1, code = NUMPAD1]
KeyEvent [source = TextField@42924cd[styleClass=text-input text-field], target = TextField@42924cd[styleClass=text-input text-field], eventType = KEY_TYPED, consumed = false, character = 1, text = , code = UNDEFINED]
KeyEvent [source = TextField@42924cd[styleClass=text-input text-field], target = TextField@42924cd[styleClass=text-input text-field], eventType = KEY_RELEASED, consumed = false, character = , text = 1, code = NUMPAD1]
换句话说,KeyTyped 事件无法区分键盘按下(code=UNDEFINED),因此您无法捕获它。
它与异常一起工作的原因与您只是使用事件而不检查任何内容的原因相同。您可以使用它并防止打字。但是,不能用键盘检查。
但话又说回来,无论如何你都不应该阻止它。应该由用户决定他想使用他的键盘或任何输入机制来做什么。
但如果你必须,你必须。鉴于该信息,此问题的解决方法可能是:
public class Main extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage primaryStage) {
HBox root = new HBox();
EventHandler<KeyEvent> handler = new EventHandler<KeyEvent>() {
private boolean willConsume = false;
@Override
public void handle(KeyEvent event) {
if (willConsume) {
event.consume();
}
if (event.getCode().isKeypadKey()) {
if (event.getEventType() == KeyEvent.KEY_PRESSED) {
willConsume = true;
} else if (event.getEventType() == KeyEvent.KEY_RELEASED) {
willConsume = false;
}
}
}
};
TextField textField = new TextField();
textField.addEventFilter(KeyEvent.ANY, handler);
// logging
textField.addEventFilter(KeyEvent.ANY, e -> System.out.println(e));
root.getChildren().addAll(textField);
Scene scene = new Scene(root, 300, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
}
这是简单版本。实际上你必须使用扩展机制来处理多个按键。
我需要检测数字小键盘的按键操作才能做一些事情。这是代码:
textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if(event.getCode().isKeypadKey()) {
//do stuff here...
event.consume();
}
}
});
假设用户在小键盘上按下“2”,虽然事件被消耗,字符“2”将出现在文本字段中。但我不想要那个。有什么想法可以防止这种情况发生吗?
更有趣的是,如果我抛出一个虚拟异常而不是使用事件,它将阻止键类型化事件。
您面临的问题可以通过添加日志监听器来解释:
textField.addEventFilter(Event.ANY, e -> System.out.println(e));
因此,当您键入一个键时,您会得到:
KeyEvent [source = TextField@42924cd[styleClass=text-input text-field], target = TextField@42924cd[styleClass=text-input text-field], eventType = KEY_PRESSED, consumed = false, character = , text = 1, code = NUMPAD1]
KeyEvent [source = TextField@42924cd[styleClass=text-input text-field], target = TextField@42924cd[styleClass=text-input text-field], eventType = KEY_TYPED, consumed = false, character = 1, text = , code = UNDEFINED]
KeyEvent [source = TextField@42924cd[styleClass=text-input text-field], target = TextField@42924cd[styleClass=text-input text-field], eventType = KEY_RELEASED, consumed = false, character = , text = 1, code = NUMPAD1]
换句话说,KeyTyped 事件无法区分键盘按下(code=UNDEFINED),因此您无法捕获它。
它与异常一起工作的原因与您只是使用事件而不检查任何内容的原因相同。您可以使用它并防止打字。但是,不能用键盘检查。
但话又说回来,无论如何你都不应该阻止它。应该由用户决定他想使用他的键盘或任何输入机制来做什么。
但如果你必须,你必须。鉴于该信息,此问题的解决方法可能是:
public class Main extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage primaryStage) {
HBox root = new HBox();
EventHandler<KeyEvent> handler = new EventHandler<KeyEvent>() {
private boolean willConsume = false;
@Override
public void handle(KeyEvent event) {
if (willConsume) {
event.consume();
}
if (event.getCode().isKeypadKey()) {
if (event.getEventType() == KeyEvent.KEY_PRESSED) {
willConsume = true;
} else if (event.getEventType() == KeyEvent.KEY_RELEASED) {
willConsume = false;
}
}
}
};
TextField textField = new TextField();
textField.addEventFilter(KeyEvent.ANY, handler);
// logging
textField.addEventFilter(KeyEvent.ANY, e -> System.out.println(e));
root.getChildren().addAll(textField);
Scene scene = new Scene(root, 300, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
}
这是简单版本。实际上你必须使用扩展机制来处理多个按键。