JavaFX KeyEvent 不执行任何操作
JavaFX KeyEvent doesn't do anything
所以我有一个小程序,你可以在行星之间驾驶你的宇宙飞船,我想用箭头键来旋转飞船。首先,我尝试将关键侦听器添加到面板,飞船确实旋转了,但只有在我按下 ctrl/alt 时才会旋转。然后我尝试将关键侦听器添加到场景中(人们说这是正确的做法,因为它不依赖于焦点),但是尽管调用了旋转船的功能,但您看不到任何东西屏幕。
主要class:
@Override
public void start(Stage stage) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("Main.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root, 700, 500);
Controller controller = new Controller();
loader.setController(controller);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
stage.setScene(scene);
stage.setFullScreen(true);
stage.show();
controller.setScene(scene);
} catch(Exception e) {
e.printStackTrace();
}
}
控制器:
@FXML
private BorderPane contentPane;
private OrbiterPanel orbiterPanel = new PerfectCirclePanel(this);
private Scene scene;
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
contentPane.setCenter(orbiterPanel);
}
public void setScene(Scene scene) {
this.scene = scene;
scene.addEventFilter(KeyEvent.KEY_PRESSED, e -> keyStrokesPressed(e));
scene.addEventFilter(KeyEvent.KEY_RELEASED, e -> keyStrokesReleased(e));
}
private void keyStrokesPressed(KeyEvent e) {
switch(e.getCode()) {
case LEFT -> {
orbiterPanel.leftPressed();
}
case RIGHT -> {
orbiterPanel.rightPressed();
}
default -> {}
}
}
private void keyStrokesReleased(KeyEvent e) {
switch(e.getCode()) {
case LEFT -> {
orbiterPanel.leftReleased();
}
case RIGHT -> {
orbiterPanel.rightReleased();
}
default -> {}
}
}
我所有“worlds/maps”的超级class:
protected AtomicReference<Spaceship> shipReference = new AtomicReference<>();
protected RotateTransition rotatingTransition;
public OrbiterPanel() {
rotatingTransition = new RotateTransition();
rotatingTransition.setCycleCount(RotateTransition.INDEFINITE);
rotatingTransition.setInterpolator(Interpolator.LINEAR);
}
protected void rightPressed() {
if(rotatingTransition.getStatus().equals(Status.RUNNING)) return;
rotatingTransition.stop();
rotatingTransition.setNode(shipReference.get());
rotatingTransition.setByAngle(360);
rotatingTransition.setDuration(Duration.seconds(2));
rotatingTransition.play();
}
protected void leftPressed() {
if(rotatingTransition.getStatus().equals(Status.RUNNING)) return;
rotatingTransition.stop();
rotatingTransition.setNode(shipReference.get());
rotatingTransition.setByAngle(-360);
rotatingTransition.setDuration(Duration.seconds(2));
rotatingTransition.play();
}
protected void rightReleased() {
rotatingTransition.stop();
}
protected void leftReleased() {
rotatingTransition.stop();
}
PerfectCirclePanel,OrbiterPanel 的一个子class,除了显示宇宙飞船和行星外,并没有做太多事情。
FXML:
<BorderPane prefHeight="607.0" prefWidth="877.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<center>
<BorderPane fx:id="contentPane" prefHeight="704.0" prefWidth="963.0" style="-fx-background-color: black;">
</BorderPane>
</center>
</BorderPane>
有两种不同的方法可以将控制器连接到 FXML 文件定义的 UI。
任一:
- 通过向 FXML 的根元素提供
fx:controller
属性来指定控制器 class。在这种情况下,默认情况下,控制器实例将通过调用其无参数构造函数从 class 创建,并且该实例将是与 UI. 关联的控制器
或:
- 在
FXMLLoader
实例上调用 setController(...)
。
当你调用loader.load()
时,如果控制器存在,控制器中的任何@FXML
注解字段将从相应的FXML元素初始化,然后initialize()
方法将被调用。
在您的代码中,您创建了两个 Controller
实例:一个是从 fx:controller
属性创建的,并与 UI 相关联。另一个是您在 Java 代码中“手动”创建的。后者未连接到 UI(未注入 @FXML
-注释字段,并且未调用 initialize()
),因为您调用 setController(...)
调用 load()
.
之后
因为有两个Controller
实例,所以有两个OrbiterPanel
实例。从 fx:controller
属性创建的那个是显示在 UI 中的那个(因为这是调用 initialize()
时引用的那个)。不显示从您在代码中创建的 Controller
实例创建的;然而,这是您的事件处理程序引用的那个。
删除 fx:controller
属性,并将调用移至 setController()
,然后再调用 load()
。
所以我有一个小程序,你可以在行星之间驾驶你的宇宙飞船,我想用箭头键来旋转飞船。首先,我尝试将关键侦听器添加到面板,飞船确实旋转了,但只有在我按下 ctrl/alt 时才会旋转。然后我尝试将关键侦听器添加到场景中(人们说这是正确的做法,因为它不依赖于焦点),但是尽管调用了旋转船的功能,但您看不到任何东西屏幕。
主要class:
@Override
public void start(Stage stage) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("Main.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root, 700, 500);
Controller controller = new Controller();
loader.setController(controller);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
stage.setScene(scene);
stage.setFullScreen(true);
stage.show();
controller.setScene(scene);
} catch(Exception e) {
e.printStackTrace();
}
}
控制器:
@FXML
private BorderPane contentPane;
private OrbiterPanel orbiterPanel = new PerfectCirclePanel(this);
private Scene scene;
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
contentPane.setCenter(orbiterPanel);
}
public void setScene(Scene scene) {
this.scene = scene;
scene.addEventFilter(KeyEvent.KEY_PRESSED, e -> keyStrokesPressed(e));
scene.addEventFilter(KeyEvent.KEY_RELEASED, e -> keyStrokesReleased(e));
}
private void keyStrokesPressed(KeyEvent e) {
switch(e.getCode()) {
case LEFT -> {
orbiterPanel.leftPressed();
}
case RIGHT -> {
orbiterPanel.rightPressed();
}
default -> {}
}
}
private void keyStrokesReleased(KeyEvent e) {
switch(e.getCode()) {
case LEFT -> {
orbiterPanel.leftReleased();
}
case RIGHT -> {
orbiterPanel.rightReleased();
}
default -> {}
}
}
我所有“worlds/maps”的超级class:
protected AtomicReference<Spaceship> shipReference = new AtomicReference<>();
protected RotateTransition rotatingTransition;
public OrbiterPanel() {
rotatingTransition = new RotateTransition();
rotatingTransition.setCycleCount(RotateTransition.INDEFINITE);
rotatingTransition.setInterpolator(Interpolator.LINEAR);
}
protected void rightPressed() {
if(rotatingTransition.getStatus().equals(Status.RUNNING)) return;
rotatingTransition.stop();
rotatingTransition.setNode(shipReference.get());
rotatingTransition.setByAngle(360);
rotatingTransition.setDuration(Duration.seconds(2));
rotatingTransition.play();
}
protected void leftPressed() {
if(rotatingTransition.getStatus().equals(Status.RUNNING)) return;
rotatingTransition.stop();
rotatingTransition.setNode(shipReference.get());
rotatingTransition.setByAngle(-360);
rotatingTransition.setDuration(Duration.seconds(2));
rotatingTransition.play();
}
protected void rightReleased() {
rotatingTransition.stop();
}
protected void leftReleased() {
rotatingTransition.stop();
}
PerfectCirclePanel,OrbiterPanel 的一个子class,除了显示宇宙飞船和行星外,并没有做太多事情。 FXML:
<BorderPane prefHeight="607.0" prefWidth="877.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<center>
<BorderPane fx:id="contentPane" prefHeight="704.0" prefWidth="963.0" style="-fx-background-color: black;">
</BorderPane>
</center>
</BorderPane>
有两种不同的方法可以将控制器连接到 FXML 文件定义的 UI。
任一:
- 通过向 FXML 的根元素提供
fx:controller
属性来指定控制器 class。在这种情况下,默认情况下,控制器实例将通过调用其无参数构造函数从 class 创建,并且该实例将是与 UI. 关联的控制器
或:
- 在
FXMLLoader
实例上调用setController(...)
。
当你调用loader.load()
时,如果控制器存在,控制器中的任何@FXML
注解字段将从相应的FXML元素初始化,然后initialize()
方法将被调用。
在您的代码中,您创建了两个 Controller
实例:一个是从 fx:controller
属性创建的,并与 UI 相关联。另一个是您在 Java 代码中“手动”创建的。后者未连接到 UI(未注入 @FXML
-注释字段,并且未调用 initialize()
),因为您调用 setController(...)
调用 load()
.
因为有两个Controller
实例,所以有两个OrbiterPanel
实例。从 fx:controller
属性创建的那个是显示在 UI 中的那个(因为这是调用 initialize()
时引用的那个)。不显示从您在代码中创建的 Controller
实例创建的;然而,这是您的事件处理程序引用的那个。
删除 fx:controller
属性,并将调用移至 setController()
,然后再调用 load()
。