javafx KeyEvent触发两次

问题描述 投票:-1回答:2

我在使用KeyEvent的项目中遇到了一些问题。按下键Enter时,将值从一个切换到另一个的组合框。

经过一些尝试后,问题显示Enter键生成了2次事件,因此组合框显然没有改变。

然后,我尝试使用此代码片段创建一个简单的测试项目:

            window.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent event) {
            if(event.getCode().equals(KeyCode.ENTER))
                System.out.println("print");
        }
    });

该程序每次输入打印两次。 KeyCode.ENTER是否可能引用多个键或类似的东西?如果我用其他东西更改KeyCode.ENTER(尝试使用SPACE或某些字母),它可以正常工作。有可能做点什么来解决这个问题吗?

我做了一个包含3个文件的简单项目:

主要

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;


public class Main extends Application {
    private static Stage window;

    @Override
    public void start(Stage primaryStage) throws Exception{
        window = primaryStage;

        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();
    }


    public static Stage getWindow(){return window;}

    public static void main(String[] args) {
        launch(args);
    }
}

控制器:

import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;

import java.net.URL;
import java.util.ResourceBundle;


public class Controller implements Initializable {

    @FXML
    TextField textField;

    Stage window;


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        window = Main.getWindow();
        window.addEventFilter(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                if (event.getCode().equals(KeyCode.ENTER))
                    System.out.println("print");
            }
        });
    }
}

样品:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>


<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity"
            minHeight="-Infinity" minWidth="-Infinity"
            prefHeight="400.0" prefWidth="600.0"
            fx:controller="Controller"
            xmlns="http://javafx.com/javafx/8.0.121"
            xmlns:fx="http://javafx.com/fxml/1">
    <children>
        <TextField fx:id="textField" layoutX="14.0" layoutY="14.0" />
    </children>
</AnchorPane>

按Enter键时打印两次。在插入TextField之前,工作正常。

javafx keyevent
2个回答
0
投票

改变这一行

window.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {

window.addEventFilter(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {

编辑@James_D的代码

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;

import java.net.URL;
import java.util.ResourceBundle;


public class Controller implements Initializable {

    @FXML
    TextField textField;

    Stage window;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        window = Main.getWindow();
        window.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
            System.out.println("Key Code:"+event.getCode()+" Target:"+event.getTarget());
        });
//        textField.setOnAction(event -> {});
    }
}

当它运行时,你得到的输出

Key Code:ENTER Target:TextField[id=textField, styleClass=text-input text-field]
Key Code:ENTER Target:AnchorPane@7a78d90b[styleClass=root]

如果取消注释textField Line的输出

Key Code:ENTER Target:TextField[id=textField, styleClass=text-input text-field]

@James_D最初我没有,但经过一些环顾四周,我认为它与预设的setOnAction命令有关,描述是“与此文本字段关联的动作处理程序,如果没有分配动作处理程序,则为null。动作处理程序通常是当用户键入ENTER键时调用。“因此,当您将.setOnAction更改为使用或不更改时,它会阻止此错误,我认为这是因为它不再将enter命令踢到anchorPane周围。现在关于为什么KeyEvent.KEY_RELEASED工作,我认为这是因为每次按下输入键只能释放一次,而不是可以多次发送命令的按键。这是完全的猜测,因为我不知道我在说什么,如果你能弄清楚为什么我想知道实际的推理。这应该是一个评论,但很长。


1
投票

我遇到过同样的问题。每个键都会触发一次EventFilter,除了ENTER,它会触发两次。

更简单和优雅的解决方案是简单地将e.consume()添加到您的块中,以响应进入EventFilter。

if(e.getCode().toString().equals("ENTER")){
    e.consume();
}
© www.soinside.com 2019 - 2024. All rights reserved.