这是javafx中事件过滤器和requstfocus的正确行为吗?

时间:2018-03-10 18:55:28

标签: javafx navigation keycode

我有一个非常简单的任务要完成。我只想按下按钮上的任何字母,匹配键代码,并将焦点移动到文本字段。我写 一个简单的测试代码如图所示。转移焦点我没有问题。然而, 我不希望我按下的那封信显示在文本字段中。看似简单的编程解决方案结果并非如此简单。

我不明白为什么事件使用方法不会阻止事件沿事件链向下传播并且在文本字段中显示了键入的字母。

似乎在调用requestFocus之后,文本字段会拾取从按钮输入的字母。这发生在Mac上。任何帮助将不胜感激。

package testkeynavigation;


public class TestKeyNavigation extends Application {

@Override
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.setOnKeyPressed((KeyEvent e) ->{
        if (e.getCode() == KeyCode.A) {
            e.consume();
            System.out.println("e.isConsumed: "+e.isConsumed());
            txt2.requestFocus();
        }

    });

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();

    btn.requestFocus();
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}

}

1 个答案:

答案 0 :(得分:0)

有三种关键事件:KEY_PRESSEDKEY_TYPEDKEY_RELEASED。在按键笔划中,每个类型的事件按此顺序触发到事件发生时具有键盘焦点的UI节点。

TextFieldKEY_TYPED个事件的内部侦听器;因此,如果在文本字段具有焦点时发生KEY_TYPED事件,则会在文本字段中输入一个字符(或者执行其他操作,例如删除字符或移动插入符号,具体取决于键)。

在您的代码中,您会听到按钮上发生的第一个 - KEY_PRESSED - 。如果按键的代码为A,则使用 事件(KEY_PRESSED事件),然后将键盘焦点转移到文本字段。稍后,用户释放密钥,由于文本字段现在具有焦点,因此会在文本字段上触发KEY_TYPED事件。请注意,这是一个新事件,因此不会使用它,因此文本字段会像输入字符一样做出反应。最后,在文本字段上触发KEY_RELEASED事件。

如果添加调试代码,您可以看到这一点:

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());
});

要解决此问题,只需侦听一系列事件中的最后一个事件:密钥释放事件。请注意,您不需要使用该事件。

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();
}