1

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 &quot;R&quot; 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)

Leik Isdal
  • 11
  • 1
  • 2
    Does this answer your question? [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – kleopatra Mar 13 '20 at 09:36
  • I don't think so. Shouldn't the ImageView object already be initialized by virtue of my scene builder FXML file linking it's fx:id to the controller class? I could be wrong. Might have to create the ImageView object in the controller class and then add it to the scene before showing the scene, but how do I do that when the scene is built in scene builder? – Leik Isdal Mar 13 '20 at 09:44
  • 1
    the comment is created automatically, forgot to delete it :) This is a duplicate because the answers to the other question guide you to find out where (you already seem to know that) and why it happens: to go from there, start experimenting: first strip down your example to be a [mcve] (mind the _M_ that is no need for tons of images/controls, just enough to make it reproducible), then modify to find when it happens and when not - bingo :) – kleopatra Mar 13 '20 at 09:54

0 Answers0