JavaFX TextField how to prevent key from getting typed in keypressed event

后端 未结 1 2005

I need to detect the numpad key presses to do some stuff. here is the code:

textField.setOnKeyPressed(new EventHandler() {
            @Ove         


        
1条回答
  •  有刺的猬
    2020-12-21 15:10

    The problem you are facing can be explained by adding a logging listener:

    textField.addEventFilter(Event.ANY, e -> System.out.println(e));
    

    So when you type a key you get this:

    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]
    

    In other words the KeyTyped event can't distinguish the keypad press (code=UNDEFINED), so you can't catch it.

    The reason why it works with an exception is the same as if you just consume the event without checking anything. You can consume it and prevent the typing. However, not with the keypad check.

    But then again, you shouldn't prevent it anyway. It should be up to the user as to what he wants to use his keypad or whatever input mechanism for.

    But if you must, you must. Given that information a workaround for this problem could be:

    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 handler = new EventHandler() {
    
                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();
    
        }
    
    }
    

    That's the simple version. Actually you'd have to use an extended mechanism in order to deal with multiple keypresses.

    0 讨论(0)
提交回复
热议问题