【发布时间】:2017-04-08 13:39:20
【问题描述】:
我现在超级困惑。 我在 fxml 代码中创建了一个窗格并设置了一个 onKeyPressed 事件。
pane.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
System.out.println( "I'm here");
jump( event);
}
});
这不起作用。 Pane 没有捕捉到任何 KeyEvent。从未打印过“我在这里”。 然后我想设置场景的onKeyPressed,它可以工作,但我必须在控制器中完成,因为我想要在按键期间处理的事情必须在控制器中完成。
然后我打电话给pane.getScene().setOnKeyPressed(),但结果却是nullPointerException,因为我发现我必须在initialize()之外打电话。
所以我创建了一个 Button 并为其附加了一个 onAction 事件,它会打印出我的窗格中的场景,以尝试它是否真的有效。
@FXML
public void printScene() {
System.out.println( pane.getScene());
}
当我单击按钮时,它会打印出我的窗格中的场景,因为它应该有。但是后来,我意识到我的窗格现在可以捕获 KeyEvents。除了使用 Fxml 添加一个按钮之外,我什么都没改变,现在窗格捕获 KeyEvents?当我注释掉按钮的代码时,窗格不再捕获 KeyEvents
<Button onAction="#printScene"/>
这是我所有的按钮代码。
注意:我也尝试了pane.requestFocus() 和pane.SetFocusTraversable( true),但也没有用。但是突然添加一个按钮就可以了?我很困惑。
整个代码:
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = fxmlLoader.load();
Scene scene = new Scene( root, 800, 600);
primaryStage.setTitle("Game");
primaryStage.setScene( scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
public class Controller {
@FXML private Pane pane;
@FXML private Rectangle cube;
public void initialize() {
pane.requestFocus();
pane.setFocusTraversable( true);
pane.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
System.out.println( "I'm here");
jump( event);
}
});
System.out.println( pane.getScene());
}
}
//FXML Code
<Pane fx:controller="sample.Controller" fx:id="pane"
xmlns:fx="http://javafx.com/fxml">
<Rectangle width="800" height="20" layoutY="580" fill="green"/>
<Rectangle fx:id="cube" width="40" height="40" layoutX="5" layoutY="540"/>
<!--<Button />-->
</Pane>
取消注释按钮使窗格获得焦点,反之亦然。
【问题讨论】:
-
不知道为什么添加按钮会给窗格带来焦点,或者为什么
pane.requestFocus()不起作用(您需要发布minimal reproducible example 才能得到答案)。最好的方法是在场景中注册一个侦听器,您可以在创建场景的地方执行此操作。此时应该也可以获取对控制器的引用,因此您可以从处理程序调用控制器上的方法。 -
我会尽快发布所有代码,感谢您的帮助。我还在 initialize() 方法中调用了 requestFocus,也许这就是它不起作用的原因?
-
@James_D 我已经发布了整个代码。如果你能看一下我会很高兴^^
-
是的,这很奇怪。我知道创建控件实例会强制加载 CSS。我想知道是否出于某种原因
requestFocus()不起作用,除非该节点是场景的一部分或已加载 CSS - 我将不得不深入研究源代码以确定这是否属实。无论如何,更安全的做法似乎是在现场注册处理程序。 -
感谢您的回复!