eventFilter consume() не предотвращает использование пробелов в текстовом поле

#javafx-8

#javafx-8

Вопрос:

У меня есть графический интерфейс JavaFX, в котором я хочу перехватить нажатие пробела и использовать его для вызова метода. Я написал eventFilter, который, кажется, делает свое дело. Он включает в себя команду event.consume(), которая, как я полагаю, должна препятствовать распространению KeyEvent на различные элементы управления.

Моя проблема в том, что когда я добавил текстовое поле, и это поле имеет фокус, нажатия пробела не используются, как я думал. » » захватываются текстовым полем. Я хотел бы перехватить и предотвратить добавление » » в текстовое поле.

Что я оставляю в приведенном ниже коде, чтобы не допустить попадания » » в текстовое поле? API, если я правильно его читаю, говорит, что фильтры, зарегистрированные в родительском элементе управления, могут перехватывать событие до того, как оно достигнет дочерних узлов. Но даже при установке фильтра непосредственно в текстовое поле у меня все еще появляются символы » » в текстовом поле.

 import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;

import javafx.scene.input.KeyEvent;

import javafx.stage.Stage;


public class SpaceIntercept extends Application implements EventHandler <KeyEvent>
{
    public static void main(String[] args) 
    {   
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) 
    {
        TextField textField = new TextField("asdf");
        Group root = new Group();
        Scene scene = new Scene(root, 200, 100);
        scene.addEventFilter(KeyEvent.ANY, event -> handle(event));        
        // root.addEventFilter(KeyEvent.ANY, event -> handle(event));
        // textField.addEventFilter(KeyEvent.ANY, event -> handle(event)); 
        root.getChildren().add(textField); 
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    @Override
    public void handle(KeyEvent event) 
    {
        if (event.getCode() == KeyCode.SPACE)
        {
            if (event.getEventType() == KeyEvent.KEY_PRESSED)
            {
                System.out.println("Code that responds to SpaceBar");
            }
            event.consume();
        }
    }       
}
  

Ответ №1:

Вероятно, текстовое поле прослушивает KEY_TYPED события. Как хорошо документировано, getCode() возвращает KeyCode.UNDEFINED для KEY_TYPED события. Таким образом, вы не улавливаете этот случай.

Вы можете проверить наличие character переменной, а также code переменной для обработки всех случаев:

 import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;

import javafx.scene.input.KeyEvent;

import javafx.stage.Stage;


public class SpaceIntercept extends Application implements EventHandler <KeyEvent>
{
    public static void main(String[] args) 
    {   
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) 
    {
        TextField textField = new TextField("asdf");
        Group root = new Group();
        Scene scene = new Scene(root, 200, 100);
        scene.addEventFilter(KeyEvent.ANY, event -> handle(event));        
        // root.addEventFilter(KeyEvent.ANY, event -> handle(event));
        // textField.addEventFilter(KeyEvent.ANY, event -> handle(event)); 
        root.getChildren().add(textField); 
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    @Override
    public void handle(KeyEvent event) 
    {
        if (event.getCode() == KeyCode.SPACE  || " ".equals(event.getCharacter()))
        {
            if (event.getEventType() == KeyEvent.KEY_PRESSED)
            {
                System.out.println("Code that responds to SpaceBar");
            }
            event.consume();
        }
    }       
}
  

Ответ №2:

Я могу придумать простое решение, которое, хотя и не блокирует добавление пробела в TextField , но заменяет его после того, как оно было добавлено почти мгновенно, — это добавление a changeListener TextProperty в TextField :

 textField.textProperty().addListener((observable,oldValue,newValue)->{  
    textField.setText(textField.getText().replace(" ", ""));
});
  

Это также может быть полезно http://fxexperience.com/2012/02/restricting-input-on-a-textfield /

Комментарии:

1. @James_D почти не видел этого. Спасибо, в любом случае я отредактировал ответ, и он работает, даже если SPACE он находится между существующим текстом. Хотя это всего лишь предположение, нужно ли это OP.

2. Я нашел этот ответ полезным. Мои первые попытки заменить содержимое текстового поля не сработали, поэтому приятно видеть, как вы это сделали. Ответ James_D был выбран, поскольку он устраняет необходимость редактирования поля.

3. @Phil Freihofner И так и должно быть. Я также не знал решения, которое James_D добавил в свой ответ 😉