如何使用KeyEvent移动Label? (JavaFX的)

时间:2018-03-11 17:13:06

标签: user-interface javafx fxml keyevent

我刚学会了如何使用带有FXML文件的JavaFX制作GUI应用程序。但有一件事我不明白。当我尝试将KeyListener添加到Label或我的FXML文件中的布局时,代码不会被执行。这是一个简单的任务,如System.out.println("worked");,没有什么复杂的(最终我想用keylistener移动Label,但现在我只想要一些简单的东西,我可以很容易地看到它是否有效)。我在某处读到你需要在Frame级别添加监听器,但我不知道如何。如果有人可以帮助我,我将非常感激 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);
}

}

我的控制器类:

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$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)

1 个答案:

答案 0 :(得分:0)

向控制器添加方法以移动标签,例如

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()方法中获取对控制器的引用(您需要使用load()中的非静态FXMLLoader方法来执行此操作),并从中调用方法密钥处理程序:

@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();
}