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
相关产品推荐
相关产品推荐

