You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX中Scene的KeyPressed事件回调被触发两次的问题

Scene的onKeyPressed回调触发两次问题

问题现象

  • 焦点在TextField上时,onKeyPressed绑定的方法会被调用两次;
  • 焦点在不可编辑组件(如Button)上时,该方法仅被调用一次。

调试信息

在调用selectBack()方法的第181行设置断点后,发现两次调用均来自Scene的同一事件。

复现环境

Java11(jdk-11.0.11)+JavaFX11(javafx-sdk-11.0.2)

项目结构

Test
|
+-src
   |
   +-application
   |         |
   |         +--Controller.java
   |         |
   |         +--Main.java
   |         |
   |         +--Test.fxml
   |
   module-info.java

代码文件

Main.java

package application;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;

public class Main extends Application {
    @Override
    public void start(Stage stage){
        try {
            FXMLLoader loader = new FXMLLoader(Main.class.getResource("Test.fxml"));
            AnchorPane root = (AnchorPane) loader.load();
            Scene scene = new Scene(root);
            stage.setTitle("Test");
            stage.setScene(scene);
            stage.show();
            
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Controller.java

package application;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.AnchorPane;

public class Controller {
    @FXML
    private AnchorPane base;
    private int counter = 0;

    public void initialize()
    {
        Platform.runLater(() -> {
            this.base.getScene().setOnKeyPressed(e -> {
                if(e.getCode() == KeyCode.ESCAPE)
                    test(new ActionEvent());
            });
        });
        
    }
    
    @FXML private void move(ActionEvent event)
    {
    }
    
    @FXML private void test(ActionEvent event)
    {
        System.out.println("Counter: " + counter + " (" + System.currentTimeMillis() + ")");
        
        Alert alert = new Alert(AlertType.INFORMATION, "Test");
        alert.setContentText("Counter: " + counter);
        alert.showAndWait();
        
        counter++;
    }
}

Test.fxml

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

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

<AnchorPane id="base" fx:id="base" prefHeight="400.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
   <children>
      <TextField layoutX="125.0" layoutY="187.0" />
      <Button layoutX="174.0" layoutY="273.0" mnemonicParsing="false" text="Button" />
   </children>
</AnchorPane>

module-info.java

module test {
    requires javafx.controls;
    requires javafx.fxml;
    requires transitive javafx.base;
    requires transitive javafx.graphics;
    
    opens application;
}

运行配置VM参数

--module-path "bin;C:\Program Files\Java\javafx-sdk-11.0.2\lib" -m test/application.Main

复现步骤

运行程序后按下ESC键:

  • 焦点在TextField上时,会显示两次Alert;
  • 焦点在Button上时,仅显示一次Alert。

内容的提问来源于stack exchange,提问作者mikyll98

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 05:24:31