如何使用 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();
}