Java 使用场景生成器在画布上绘制

Java 使用场景生成器在画布上绘制,java,javafx,scenebuilder,Java,Javafx,Scenebuilder,现在我正在玩JavaFX,我想做的是在已经用Scene Builder创建的画布上绘制某种动画。不幸的是,我无法在画布上获得任何东西,因为每当我使用GraphicsContext做一些事情时,都会出现一些异常 我对Java和JavaFX都很陌生,我一直在寻找解决这个问题的方法,但我就是无法解决它 循环似乎正在成功运行,因为我能够获得控件打印,但是任何与在gameCanvasCanvas上渲染图形相关的操作都会触发异常 错误:(例如,由于run()方法中的gc.setFill(Color.RED)

现在我正在玩JavaFX,我想做的是在已经用Scene Builder创建的画布上绘制某种动画。不幸的是,我无法在画布上获得任何东西,因为每当我使用GraphicsContext做一些事情时,都会出现一些异常

我对Java和JavaFX都很陌生,我一直在寻找解决这个问题的方法,但我就是无法解决它

循环似乎正在成功运行,因为我能够获得控件打印,但是任何与在
gameCanvas
Canvas上渲染图形相关的操作都会触发异常

错误:(例如,由于
run()
方法中的
gc.setFill(Color.RED)
,我得到了这些错误

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at Game.lambda$0(Game.java:54)
    at javafx.graphics/com.sun.scenario.animation.shared.TimelineClipCore.visitKeyFrame(Unknown Source)
    at javafx.graphics/com.sun.scenario.animation.shared.TimelineClipCore.playTo(Unknown Source)
    at javafx.graphics/javafx.animation.Timeline.doPlayTo(Unknown Source)
    at javafx.graphics/javafx.animation.AnimationAccessorImpl.playTo(Unknown Source)
    at javafx.graphics/com.sun.scenario.animation.shared.InfiniteClipEnvelope.timePulse(Unknown Source)
    at javafx.graphics/javafx.animation.Animation.doTimePulse(Unknown Source)
    at javafx.graphics/javafx.animation.Animation$1.lambda$timePulse$0(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/javafx.animation.Animation$1.timePulse(Unknown Source)
    at javafx.graphics/com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(Unknown Source)
    at javafx.graphics/com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(Unknown Source)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(Unknown Source)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(Unknown Source)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(Unknown Source)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(Unknown Source)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(Unknown Source)
    at java.base/java.lang.Thread.run(Unknown Source)
我的代码:

import java.net.URL;
import java.util.ResourceBundle;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.util.Duration;
import javafx.scene.shape.*;

public class Game implements Initializable, Runnable, ControlledScreen {

    @FXML
    public Canvas gameCanvas;
    private GraphicsContext gc;
    public enum difficulties {EASY, MEDIUM, HARD};

    difficulties difficultyLevel;
    int score = 0;
    Snake snake;
    Food food;
    boolean running = true;
    private Timeline gameloop = new Timeline();

    @Override
    public void setScreenParent(ScreensController screenPage) {

    }

    public void setLevelEasy() {
        difficultyLevel = difficulties.EASY;
    }

    public void setLevelMedium() {
        difficultyLevel = difficulties.MEDIUM;
    }

    public void setLevelHard() {
        difficultyLevel = difficulties.HARD;
    }

    @Override

    public void run() { 

        KeyFrame frame = new KeyFrame(Duration.seconds(0.2), event -> {
            if (!running)
                return;
            System.out.println("The loop's running, yai!");

            gc.setFill(Color.RED);

        });

        gameloop.getKeyFrames().add(frame);
        gameloop.setCycleCount(Timeline.INDEFINITE);
        gameloop.play();

    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        gc = gameCanvas.getGraphicsContext2D();
    }

}

提前感谢!

您从哪里调用
run()
?在这里让控制器实现
Runnable
似乎没有意义。@James\u D它是在新游戏对象实例化之后从另一个类调用的。您确定
run()吗
正在实际控制器和FX应用程序线程上调用?@James\u D是的,游戏类是一个控制器,但我没有真正理解第二部分。请详细说明一下,好吗?“游戏类是控制器”没有真正的意义。控制器是一个特定的对象(通常由
FXMLLoader
创建),不是类。
@FXML
-注释字段仅在相关控制器中初始化。我询问了线程,因为通常实现
Runnable
的目的是在后台线程上执行
run()
方法。您在
run()中的代码
必须在FX应用程序线程上执行,而不是在后台线程上执行。