Мне известно, что подобные вопросы задавались ранее в Stackoverflow, но ни один из найденных ответов, похоже, не решил мою проблему. Также я хотел бы добавить, что я совершенно новичок в javafx и начал кодировать java буквально в неделю go в целом, поэтому я прошу прощения за любые глупые ошибки в моем коде! При попытке переместить ImageView в моем javafx, перемещении игрока и ящиков в игре «sokoban», я получаю nullpointerexception, утверждающее, что мой ImageView, помеченный fx: id в построителе сцены и затем вызванный в моем классе контроллера, является нулевым объектом. Вот мой код: Приложение:
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);
}
}
Контроллер:
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);
}
}
}
}
}
F XML -файл:
<?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>
Мое приложение начинается с первоначального выбора сложности сцена, а затем переключается на реальную игровую сцену, где я столкнулся с проблемой.
Это ошибка, которую я получаю:
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)
(строка 97 является первой точкой, в которой Я пытаюсь вызвать метод на объекте ImageView playerEasy)