I've tried my hardest to get a button to change scenes but I can't get it to work.
I'm getting a nullpointerexception when I click on the button. It's something to do with the button2action method in the controller class. I know it's linked up correctly with the FXML because of the debug message I'm printing when it's clicked on.
I've spent many hours in vain trying to get this to work as you might be able to see from all the crap I've commented out in the main class (some of this might have worked with tweaks so I've left it in just in case someone can spot something I can't in that mess).
Here is my controller:
package com.frogger.mainapp;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Scene;
public class SampleController {
@FXML
public void button2action(ActionEvent event) {
System.out.println("This is horrible!");
Main.primaryStage.setScene(Main.scene);
Main.primaryStage.centerOnScreen();
Main.animal2 = new Animal("file:resources/froggerUp.png", 400.00, 700.00, true);
Main.background.add(Main.animal2);
}
}
Here is my FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="558.0" prefWidth="355.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.frogger.mainapp.SampleController">
<children>
<VBox alignment="CENTER" prefHeight="558.0" prefWidth="355.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<!-- fitHeight="183.0" fitWidth="355.0"-->
<ImageView pickOnBounds="true" preserveRatio="true" VBox.vgrow="ALWAYS">
<image>
<Image url="@Frogger_background_top.png" />
</image>
</ImageView>
<Button alignment="CENTER" mnemonicParsing="false" prefHeight="131.0" prefWidth="610.0" style="-fx-background-color: green;" text="Single Player Mode">
<font>
<Font name="Comic Sans MS Bold" size="28.0" />
</font>
</Button>
<Button fx:id="bt2" mnemonicParsing="false" onAction="#button2action" prefHeight="149.0" prefWidth="653.0" style="-fx-background-color: red;" text="Two Player Mode">
<font>
<Font name="Comic Sans MS Bold" size="28.0" />
</font>
</Button>
<Button mnemonicParsing="false" prefHeight="137.0" prefWidth="355.0" style="-fx-background-color: blue;" text="High Score">
<font>
<Font name="Comic Sans MS Bold" size="28.0" />
</font>
</Button>
</children>
</VBox>
</children>
</AnchorPane>
Here is my main class:
package com.frogger.mainapp;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class Main extends Application {
AnimationTimer timer;
public static MyStage background;
Animal animal;
public static Animal animal2;
public static Stage primaryStage;
public static Scene scene;
private boolean secondPlayer;
@FXML private Button bt2;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
background = new MyStage();
scene = new Scene(background,600,800);
// scene = new Scene(background,600,800);
//loginScene buttons
// Label label1= new Label("Welcome to my Frogger Game");
// Button button1= new Button("Single Player Mode");
// Button button2= new Button("Two Player Mode");
// bt2.addEventHandler(ActionEvent.ACTION, (e)->{
// animal2 = new Animal("file:resources/froggerUp.png", 400.00, 700.00, true);
// background.add(animal2);
// primaryStage.setScene(scene);
// primaryStage.centerOnScreen();
// });
//
// });
//Todo: Get the buttons working
//setting up loginScene
// VBox layout1 = new VBox(20);
// Image image = new Image("file:Frogger_background.png");
// ImageView iv1 = new ImageView();
// iv1.setImage(image);
// Image image = new Image("file:Frogger_background.png");
// BackgroundSize backgroundSize = new BackgroundSize(320, 480, true, true, true, false);
// BackgroundImage loginBack = new BackgroundImage(image, BackgroundRepeat.REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER, backgroundSize);
// layout1.setBackground(new Background(loginBack));
// layout1.getChildren().addAll(label1, button1, button2);
Parent root = FXMLLoader.load(getClass().getResource("/Sample.fxml"));
Scene loginScene = new Scene(root,320, 480);
// button2action(primaryStage, scene);
// String css = Main.class.getResource("application.css").toExternalForm();
// loginScene.getStylesheets().add(css);
primaryStage.setResizable(false);
primaryStage.setScene(loginScene);
primaryStage.show();
// scene.getStylesheets().add(getClass().getResource("/application.css").toExternalForm());
MyBackgroundImage froggerback = new MyBackgroundImage("file:resources/iKogsKW.png");
background.add(froggerback);
background.add(new Log("file:resources/log3.png", 150, 0, 166, 0.75));
background.add(new Log("file:resources/log3.png", 150, 220, 166, 0.75));
background.add(new Log("file:resources/log3.png", 150, 440, 166, 0.75));
background.add(new Log("file:resources/logs.png", 300, 0, 276, -2));
background.add(new Log("file:resources/logs.png", 300, 400, 276, -2));
background.add(new Log("file:resources/log3.png", 150, 50, 329, 0.75));
background.add(new Log("file:resources/log3.png", 150, 270, 329, 0.75));
background.add(new Log("file:resources/log3.png", 150, 490, 329, 0.75));
background.add(new Turtle(500, 376, -1, 130, 130));
background.add(new Turtle(300, 376, -1, 130, 130));
background.add(new WetTurtle(700, 376, -1, 130, 130));
background.add(new WetTurtle(600, 217, -1, 130, 130));
background.add(new WetTurtle(400, 217, -1, 130, 130));
background.add(new WetTurtle(200, 217, -1, 130, 130));
background.add(new End(13,96));
background.add(new End(141,96));
background.add(new End(141 + 141-13,96));
background.add(new End(141 + 141-13+141-13+1,96));
background.add(new End(141 + 141-13+141-13+141-13+3,96));
animal = new Animal("file:resources/froggerUp.png", 150.00, 700.00, false);
background.add(animal);
background.add(new Obstacle("file:resources/truck1"+"Right.png", 0, 649, 1, 120, 120));
background.add(new Obstacle("file:resources/truck1"+"Right.png", 300, 649, 1, 120, 120));
background.add(new Obstacle("file:resources/truck1"+"Right.png", 600, 649, 1, 120, 120));
background.add(new Obstacle("file:resources/car1Left.png", 100, 597, -1, 50, 50));
background.add(new Obstacle("file:resources/car1Left.png", 250, 597, -1, 50, 50));
background.add(new Obstacle("file:resources/car1Left.png", 400, 597, -1, 50, 50));
background.add(new Obstacle("file:resources/car1Left.png", 550, 597, -1, 50, 50));
background.add(new Obstacle("file:resources/truck2Right.png", 0, 540, 1, 200, 200));
background.add(new Obstacle("file:resources/truck2Right.png", 500, 540, 1, 200, 200));
background.add(new Obstacle("file:resources/car1Left.png", 500, 490, -5, 50, 50));
background.add(new Digit(0, 30, 360, 25));
background.start();
start();
}
// @FXML
// public void button2action(ActionEvent event){
// primaryStage.setScene(scene);
// primaryStage.centerOnScreen();
// animal2 = new Animal("file:resources/froggerUp.png", 400.00, 700.00, true);
// background.add(animal2);
// }
// @FXML
// public void initialize(){
// bt2.addEventHandler(ActionEvent.ACTION, (e)->{
//
// });
// }
public void createTimer() {
timer = new AnimationTimer() {
// @Override
public void handle(long now) {
if (animal.changeScore()) {
setNumber(animal.getPoints());
}
if (animal.getStop()) {
System.out.print("STOP");
background.stopMusic();
stop();
background.stop();
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("You Have Won The Game!");
alert.setHeaderText("Your High Score: " + animal.getPoints() + "!");
alert.setContentText("Highest Possible Score: 800");
alert.show();
}
}
};
}
public void start() {
background.playMusic();
createTimer();
timer.start();
}
public void stop() {
timer.stop();
}
public void setNumber(int n) {
int shift = 0;
while (n > 0) {
int d = n / 10;
int k = n - d * 10;
n = d;
background.add(new Digit(k, 30, 360 - shift, 25));
shift+=30;
}
}
public static Stage getStage(){
return primaryStage;
}
// public static Scene getScene(){
// return scene;
// }
public void setSecondPlayer(boolean _secondPlayer) {
this.secondPlayer = _secondPlayer;
}
public boolean getSecondPlayer(){
return this.secondPlayer;
}
}
Here is the stack trace:
"C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.3\jbr\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.3\lib\idea_rt.jar=56118:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.3\bin" -Dfile.encoding=UTF-8 -p "C:\Users\Joshu\Documents\SECOND YEAR\Software Maintenance\Frogger\out\production\froggerSWM" -m com.frogger.mainapp/com.frogger.mainapp.Main
This is horrible!
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1787)
at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670)
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.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:49)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8865)
at javafx.controls/javafx.scene.control.Button.fire(Button.java:200)
at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:206)
at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
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.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$MouseHandler.process(Scene.java:3876)
at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1300(Scene.java:3604)
at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1874)
at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2613)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:395)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433)
at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556)
at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942)
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:175)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1782)
... 47 more
Caused by: java.lang.NullPointerException
at com.frogger.mainapp/com.frogger.mainapp.SampleController.button2action(SampleController.java:12)
... 58 more
Your log says you get a NullPointerException at line number 12:
at com.frogger.mainapp/com.frogger.mainapp.SampleController.button2action(SampleController.java:12)
Now we will go to line number 12:
Main.primaryStage.setScene(Main.scene);
The application is going to access setScene
method from primaryStage
object, which is static in Main
class.
but have you initialized it in Main class?
No.
As you can see the declaration of primaryStage
in Main class:
public static Stage primaryStage;
But nowhere in the code, I found primaryStage = something.
I think you confused with the method variable of start
method with your static variable.
try to set primaryStage
you received in start
method to the static variable you created:
@Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
I think this helps you: If you have any another approach let me know.