如何使用 KeyEvent 移动标签? (JavaFX)
How can I move a Label with a KeyEvent? (JavaFX)
我刚刚学习了如何使用带有 FXML 文件的 JavaFX 制作 GUI 应用程序。不过有一件事我不明白。当我尝试将 KeyListener 添加到 FXML 文件中的标签或布局时,代码没有执行。这是一个像 System.out.println("worked");
这样的简单任务,没有什么复杂的(最终我想用 keylistener 移动标签,但现在我只想要一些简单的东西,我可以很容易地看到它是否有效)。我在某处读到您需要在框架级别添加侦听器,但我不知道如何添加。如果有人能帮助我,我将不胜感激
Main.java:
package sample;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
Scene scene = new Scene(root, 600, 600);
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>()
{
@Override
public void handle(KeyEvent event) {
Controller controller = new Controller();
controller.moveLabel(event);
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我的控制器class:
package sample;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.input.KeyEvent;
public class Controller {
@FXML
private Label label;
@FXML
public void moveLabel(KeyEvent e){
switch (e.getCode()){
case RIGHT:
label.setTranslateX(3);
break;
default:
System.out.println("not possible");
}
}
}
我的 FXML 文件:
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Label?>
<GridPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10"
vgap="10">
<Label text="Text" fx:id="label" ></Label>
</GridPane
错误信息:
Exception in thread "JavaFX Application Thread"
java.lang.NullPointerException
at sample.Controller.moveLabel(Controller.java:15)
at sample.Main.handle(Main.java:22)
at sample.Main.handle(Main.java:18)
at
com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handle
BubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent
(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent
(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent
(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent
(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent
(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent
(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent
(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent
(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$KeyHandler.process(Scene.java:3964)
at javafx.scene.Scene$KeyHandler.access00(Scene.java:3910)
at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040)
at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2501)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run
(GlassViewEventHandler.java:217)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run
(GlassViewEventHandler.java:149)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent2
(GlassViewEventHandler.java:248)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock
(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent
(GlassViewEventHandler.java:247)
at com.sun.glass.ui.View.handleKeyEvent(View.java:546)
at com.sun.glass.ui.View.notifyKey(View.java:966)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null7
(WinApplication.java:177)
at java.lang.Thread.run(Thread.java:748)
向您的控制器添加一个方法来移动标签,例如
public class Controller {
private final double moveDelta = 10 ;
@FXML
private Label labelTest ;
public void moveLabel(int deltaX, int deltaY) {
labelTest.setTranslateX(labelTest.getTranslateX() + moveDelta * deltaX);
labelTest.setTranslateY(labelTest.getTranslateY() + moveDelta * deltaY);
}
}
然后在start()
方法中获取控制器的引用(需要使用FXMLLoader
中的non-staticload()
方法),调用来自密钥处理程序的方法:
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = loader.load();
primaryStage.setTitle("Hello World");
Scene scene = new Scene(root, 600, 600);
Controller controller = loader.getController();
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
switch(event.getCode()){
case RIGHT:
controller.moveLabel(1, 0);
break;
default:
System.out.println("not possible");
}
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
我刚刚学习了如何使用带有 FXML 文件的 JavaFX 制作 GUI 应用程序。不过有一件事我不明白。当我尝试将 KeyListener 添加到 FXML 文件中的标签或布局时,代码没有执行。这是一个像 System.out.println("worked");
这样的简单任务,没有什么复杂的(最终我想用 keylistener 移动标签,但现在我只想要一些简单的东西,我可以很容易地看到它是否有效)。我在某处读到您需要在框架级别添加侦听器,但我不知道如何添加。如果有人能帮助我,我将不胜感激
Main.java:
package sample;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
Scene scene = new Scene(root, 600, 600);
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>()
{
@Override
public void handle(KeyEvent event) {
Controller controller = new Controller();
controller.moveLabel(event);
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我的控制器class:
package sample;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.input.KeyEvent;
public class Controller {
@FXML
private Label label;
@FXML
public void moveLabel(KeyEvent e){
switch (e.getCode()){
case RIGHT:
label.setTranslateX(3);
break;
default:
System.out.println("not possible");
}
}
}
我的 FXML 文件:
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Label?>
<GridPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10"
vgap="10">
<Label text="Text" fx:id="label" ></Label>
</GridPane
错误信息:
Exception in thread "JavaFX Application Thread"
java.lang.NullPointerException
at sample.Controller.moveLabel(Controller.java:15)
at sample.Main.handle(Main.java:22)
at sample.Main.handle(Main.java:18)
at
com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handle
BubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent
(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent
(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent
(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent
(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent
(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent
(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent
(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent
(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$KeyHandler.process(Scene.java:3964)
at javafx.scene.Scene$KeyHandler.access00(Scene.java:3910)
at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040)
at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2501)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run
(GlassViewEventHandler.java:217)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run
(GlassViewEventHandler.java:149)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent2
(GlassViewEventHandler.java:248)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock
(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent
(GlassViewEventHandler.java:247)
at com.sun.glass.ui.View.handleKeyEvent(View.java:546)
at com.sun.glass.ui.View.notifyKey(View.java:966)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null7
(WinApplication.java:177)
at java.lang.Thread.run(Thread.java:748)
向您的控制器添加一个方法来移动标签,例如
public class Controller {
private final double moveDelta = 10 ;
@FXML
private Label labelTest ;
public void moveLabel(int deltaX, int deltaY) {
labelTest.setTranslateX(labelTest.getTranslateX() + moveDelta * deltaX);
labelTest.setTranslateY(labelTest.getTranslateY() + moveDelta * deltaY);
}
}
然后在start()
方法中获取控制器的引用(需要使用FXMLLoader
中的non-staticload()
方法),调用来自密钥处理程序的方法:
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = loader.load();
primaryStage.setTitle("Hello World");
Scene scene = new Scene(root, 600, 600);
Controller controller = loader.getController();
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
switch(event.getCode()){
case RIGHT:
controller.moveLabel(1, 0);
break;
default:
System.out.println("not possible");
}
}
});
primaryStage.setScene(scene);
primaryStage.show();
}