Q:

How can I move a Label with a KeyEvent? (JavaFX)

I just learned how to make a GUI application with JavaFX with a FXML file. There is one thing that I don't understand though. When I try to add a KeyListener to a Label or the layout in my FXML file, the code doesn't get executed. It is a simple task like System.out.println("worked");, nothing complicated(eventually I want to move the Label with the keylistener, but now I just wanted something simple where I could easily see if it worked). I read somewhere that you need to add the listener on Frame level, but I don't know how. I would really appreciate it if someone could help me
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);
}

}

My controller 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");
        }
    }
}

My FXML file:
 <?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

Error message:
Exception in thread "JavaFX Application Thread" 
java.lang.NullPointerException
at sample.Controller.moveLabel(Controller.java:15)
at sample.Main$1.handle(Main.java:22)
at sample.Main$1.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.access$1800(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$handleKeyEvent$352
(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$null$147
(WinApplication.java:177)
at java.lang.Thread.run(Thread.java:748)

A:

Add a method to your controller to move the label, e.g.
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);
    }
}

Then get a reference to the controller in the start() method (you need to use the non-static load() method from FXMLLoader to do this), and call the method from the key handler:
@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();
}

