I'm aware that similar questions have been asked on Stackoverflow before, but none of the answers I've found seem to fix my problem. Also I'd like to add that I'm entirely new to javafx and started coding java literally a week ago altogether, so I apologize for any silly errors in my code! When trying to move an ImageView in my javafx, moving a player and crates around in the game "sokoban", I get a nullpointerexception stating that my ImageView, marked with an fx:id in scene builder and then called on in my controller class, is a null object. Here's my code: Application:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class App extends Application{
@Override
public void start(final Stage primaryStage) throws Exception {
primaryStage.setTitle("Sokoban");
primaryStage.setScene(new Scene(FXMLLoader.load(App.class.getResource("StartScreen.fxml"))));
primaryStage.show();
}
public static void main(final String[] args) {
App.launch(args);
}
}
Controller:
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
public class SokobanController {
GameState currentGame;
int stepSize;
@FXML Button Easy;
@FXML Button Medium;
@FXML Button Hard;
@FXML AnchorPane easyGameScene;
@FXML AnchorPane mediumGameScene;
@FXML AnchorPane hardGameScene;
@FXML ImageView playerEasy;
@FXML ImageView crateEasy0;
@FXML ImageView crateEasy1;
@FXML ImageView crateEasy2;
@FXML ImageView crateEasy3;
List<ImageView> crateImagesEasy =
Arrays.asList(crateEasy0,crateEasy1,crateEasy2,crateEasy3);
@FXML void handleDifficultySelection(ActionEvent event) throws IOException {
String difficulty = ((Button) event.getSource()).getId();
System.out.println(difficulty);
if (difficulty.equals("Easy")) {
stepSize = 75;
}
else if (difficulty.equals("Medium")) {
}
else if (difficulty.equals("Hard")) {
}
currentGame = new GameState(difficulty);
// playerEasy = new ImageView(new Image("@player.png"));
Scene gameScene = new Scene(FXMLLoader.load(getClass().getResource("GameScreen.fxml")));
gameScene.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
handleOnKeyPressed(event);
}
});
Stage window = (Stage)((Node)event.getSource()).getScene().getWindow();
window.setScene(gameScene);
window.show();
}
@FXML void handleOnkey(ActionEvent event) {
System.out.println("hallo");
}
void handleOnKeyPressed(KeyEvent event) {
System.out.println("hallo");
if (event.getCode().equals(KeyCode.LEFT)) {
// Translate translate = new Translate();
// translate.setX(-stepSize);
if (!currentGame.checkCollideWall(-1, 0)) {
int i = 0;
for (Crate crate : currentGame.crates) {
if (currentGame.checkCollideCrate(crate, -1, 0)
&& !currentGame.checkCollideWall(-2, 0)) {
// crateImagesEasy.get(currentGame.crates.indexOf(crate))
// .getTransforms().addAll(translate);
crateImagesEasy.get(currentGame.crates.indexOf(crate)).relocate(-stepSize,0);
// playerEasy.getTransforms().addAll(translate);
i = 1;
playerEasy.relocate(-stepSize, 0);
}
}
if (i == 0) {
// playerEasy.getTransforms().addAll(translate);
playerEasy.relocate(-stepSize, 0);
}
}
}
else if (event.getCode().equals(KeyCode.RIGHT)) {
Translate translate = new Translate();
translate.setX(stepSize);
if (!currentGame.checkCollideWall(1, 0)) {
int i = 0;
for (Crate crate : currentGame.crates) {
if (currentGame.checkCollideCrate(crate, 1, 0)
&& !currentGame.checkCollideWall(2, 0)) {
crateImagesEasy.get(currentGame.crates.indexOf(crate))
.getTransforms().addAll(translate);
playerEasy.getTransforms().addAll(translate);
i = 1;
}
}
if (i == 0) {
playerEasy.getTransforms().addAll(translate);
}
}
}
else if (event.getCode().equals(KeyCode.UP)) {
Translate translate = new Translate();
translate.setY(-stepSize);
if (!currentGame.checkCollideWall(0, -1)) {
int i = 0;
for (Crate crate : currentGame.crates) {
if (currentGame.checkCollideCrate(crate, 0, -1)
&& !currentGame.checkCollideWall(0, -2)) {
crateImagesEasy.get(currentGame.crates.indexOf(crate))
.getTransforms().addAll(translate);
playerEasy.getTransforms().addAll(translate);
i = 1;
}
}
if (i == 0) {
playerEasy.getTransforms().addAll(translate);
}
}
}
else if (event.getCode().equals(KeyCode.DOWN)) {
Translate translate = new Translate();
translate.setY(stepSize);
if (!currentGame.checkCollideWall(0, 1)) {
int i = 0;
for (Crate crate : currentGame.crates) {
if (currentGame.checkCollideCrate(crate, 0, 1)
&& !currentGame.checkCollideWall(0, 2)) {
crateImagesEasy.get(currentGame.crates.indexOf(crate))
.getTransforms().addAll(translate);
playerEasy.getTransforms().addAll(translate);
i = 1;
}
}
if (i == 0) {
playerEasy.getTransforms().addAll(translate);
}
}
}
}
}
FXML-file:
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Circle?>
<?import javafx.scene.shape.Rectangle?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane prefHeight="630.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="app.SokobanController">
<children>
<VBox prefHeight="630.0" prefWidth="600.0">
<children>
<StackPane prefHeight="600.0" prefWidth="600.0">
<children>
<AnchorPane fx:id="easyGameScene" prefHeight="600.0" prefWidth="600.0" style="-fx-background-color: f3e1bb;">
<children>
<ImageView fitHeight="75.0" fitWidth="75.0" pickOnBounds="true" translateX="150.0">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="150.0" layoutY="150.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="150.0" layoutY="225.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutY="225.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutY="300.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutY="375.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="75.0" layoutY="225.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="150.0" layoutY="75.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="225.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="300.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="300.0" layoutY="75.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="300.0" layoutY="150.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="375.0" layoutY="150.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="450.0" layoutY="150.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="525.0" layoutY="150.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="525.0" layoutY="225.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="525.0" layoutY="300.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="450.0" layoutY="300.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="375.0" layoutY="300.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="375.0" layoutY="375.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="375.0" layoutY="450.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="375.0" layoutY="525.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="300.0" layoutY="525.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="225.0" layoutY="525.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="225.0" layoutY="450.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="225.0" layoutY="375.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="150.0" layoutY="375.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fitHeight="75.0" fitWidth="75.0" layoutX="75.0" layoutY="375.0" pickOnBounds="true">
<image>
<Image url="@wall.PNG" />
</image>
</ImageView>
<ImageView fx:id="crateEasy0" fitHeight="75.0" fitWidth="75.0" layoutX="225.0" layoutY="225.0" pickOnBounds="true">
<image>
<Image url="@crate.png" />
</image>
</ImageView>
<ImageView fx:id="crateEasy2" fitHeight="75.0" fitWidth="75.0" layoutX="225.0" layoutY="300.0" pickOnBounds="true">
<image>
<Image url="@crate.png" />
</image>
</ImageView>
<ImageView fx:id="crateEasy3" fitHeight="75.0" fitWidth="75.0" layoutX="300.0" layoutY="375.0" pickOnBounds="true">
<image>
<Image url="@crate.png" />
</image>
</ImageView>
<ImageView fx:id="crateEasy1" fitHeight="75.0" fitWidth="75.0" layoutX="375.0" layoutY="225.0" pickOnBounds="true">
<image>
<Image url="@crate.png" />
</image>
</ImageView>
<ImageView fx:id="playerEasy" fitHeight="75.0" fitWidth="75.0" layoutX="300.0" layoutY="300.0" pickOnBounds="true">
<image>
<Image url="@player.png" />
</image>
</ImageView>
<Circle fill="#eb6020" layoutX="113.0" layoutY="338.0" radius="15.0" stroke="BLACK" strokeType="INSIDE" />
<Circle fill="#eb6020" layoutX="263.0" layoutY="113.0" radius="15.0" stroke="BLACK" strokeType="INSIDE" />
<Rectangle arcHeight="5.0" arcWidth="5.0" fill="#f5f5f500" height="75.0" layoutX="75.0" layoutY="300.0" stroke="#eb6020" strokeType="INSIDE" strokeWidth="5.0" width="75.0" />
<Circle fill="#eb6020" layoutX="488.0" layoutY="263.0" radius="15.0" stroke="BLACK" strokeType="INSIDE" />
<Circle fill="#eb6020" layoutX="338.0" layoutY="488.0" radius="15.0" stroke="BLACK" strokeType="INSIDE" />
<Rectangle arcHeight="5.0" arcWidth="5.0" fill="#f5f5f500" height="75.0" layoutX="225.0" layoutY="75.0" stroke="#eb6020" strokeType="INSIDE" strokeWidth="5.0" width="75.0" />
<Rectangle arcHeight="5.0" arcWidth="5.0" fill="#f5f5f500" height="75.0" layoutX="450.0" layoutY="225.0" stroke="#eb6020" strokeType="INSIDE" strokeWidth="5.0" width="75.0" />
<Rectangle arcHeight="5.0" arcWidth="5.0" fill="#f5f5f500" height="75.0" layoutX="300.0" layoutY="451.0" stroke="#eb6020" strokeType="INSIDE" strokeWidth="5.0" width="75.0" />
</children>
</AnchorPane>
</children>
</StackPane>
<HBox alignment="CENTER" prefHeight="30.0" prefWidth="600.0" style="-fx-background-color: #000000;">
<children>
<Text fill="#d79420" strokeType="OUTSIDE" strokeWidth="0.0" text="Controls: move with arrow-keys and press "R" to restart the game">
<font>
<Font name="System Bold" size="15.0" />
</font>
</Text>
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>
My application starts with an initial difficulty selection scene and then switches over to the actual game scene, where I've encountered the problem.
This is the error I get:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at ovinger/app.SokobanController.handleOnKeyPressed(SokobanController.java:97)
at ovinger/app.SokobanController$1.handle(SokobanController.java:64)
at ovinger/app.SokobanController$1.handle(SokobanController.java:1)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Scene$KeyHandler.process(Scene.java:4058)
at javafx.graphics/javafx.scene.Scene$KeyHandler.access$1500(Scene.java:4004)
at javafx.graphics/javafx.scene.Scene.processKeyEvent(Scene.java:2121)
at javafx.graphics/javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2595)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:217)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:149)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$1(GlassViewEventHandler.java:248)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:390)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:247)
at javafx.graphics/com.sun.glass.ui.View.handleKeyEvent(View.java:547)
at javafx.graphics/com.sun.glass.ui.View.notifyKey(View.java:971)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:830)
(Line 97 is the first point in which I try to call a method on the ImageView object playerEasy)