This is PART of my GoldMiner class where the problem is occuring. I am getting a null pointer. I assume it is because of the way I declared my sceneController class.

private static Game game;
private static sceneController controller;

public static void main(String[] args)
    {
        Application.launch(GoldMiner.class, (java.lang.String[])null);
        game = new Game();
        running = true;
        tick();     //Line 26
    }

//Line 44: update();

private static void update()
{
    controller.totalGoldLabel.setText(Float.toString(game.getTotalGold())); //Line 52
    controller.currentGoldLabel.setText(Float.toString(game.getCurGold()));
}

Error

Exception in thread "main" java.lang.NullPointerException
    at com.github.geodox.goldminer.GoldMiner.update(GoldMiner.java:52)
    at com.github.geodox.goldminer.GoldMiner.tick(GoldMiner.java:44)
    at com.github.geodox.goldminer.GoldMiner.main(GoldMiner.java:26)
Exception in thread "JavaFX Application Thread"

sceneController is just the FX Controller, and it is using the GoldMiner.game instance set up like Game game; and being used like game.addGold(game.getPerClickGold());

Recommended Answers

All 15 Replies

Standard procedure: print all the variables at that line to see which one is null. It could be controller, controller.totalGoldLabel, game, or the returned value from game.getTotalGold()

I do question the use of this a bit:
(java.lang.String[])null

What do you mean Stultuske?
System.out.println(); is not printing, is it because it is a JavaFX Application? So I cannot find which is null.
The error is being produced from the click event.

java.lang.NullPointerException
    at com.github.geodox.goldminer.sceneController$1.handle(sceneController.java:105)
    at com.github.geodox.goldminer.sceneController$1.handle(sceneController.java:1)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28)
    at javafx.event.Event.fireEvent(Event.java:171)
    at javafx.scene.Node.fireEvent(Node.java:6867)
    at javafx.scene.control.Button.fire(Button.java:179)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:193)
    at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:336)
    at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:329)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:64)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33)
    at javafx.event.Event.fireEvent(Event.java:171)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3369)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3209)
    at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3164)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1582)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2267)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:250)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:173)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:292)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:530)
    at com.sun.glass.ui.View.notifyMouse(View.java:924)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:17)
    at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:67)
    at java.lang.Thread.run(Unknown Source)
Exception in thread "main" java.lang.NullPointerException
    at com.github.geodox.goldminer.GoldMiner.update(GoldMiner.java:54)
    at com.github.geodox.goldminer.GoldMiner.tick(GoldMiner.java:46)
    at com.github.geodox.goldminer.GoldMiner.main(GoldMiner.java:26)
Exception in thread "JavaFX Application Thread" 

Code for the EventHandler

clickMine.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                game.addGold(game.getPerClickGold());
                game.addClickCount();
            }
        });

clickMine is the button.

Maybe that code is running off the Application.launch - before you initialise the game variable?

<update> Javadoc for launch...

public static void launch(java.lang.String... args)

Launch a standalone application. <snip>
The launch method does not return until the application has exited, either via a call to Platform.exit or all of the application windows have been closed.

which implies your game = new Game(); won't be executed, so you will get a NPE anytime a callback tries to use it.

ps System.out.println("Hello"); does work. Are you starting the application from the project level... it doesn't work properly if you just run the main class file

Im calling everything from the main method.
I managed to print which is null, and I was doing it like

System.out.println(controller);
System.out.println(controller.totalGoldLabel);
System.out.println(game);
System.out.println(game.getTotalGold());

But I only got 1 returned value, so I commented out the print for controller, and it was the returned value which happened to be null.

That's why its better to System.out.println("controller: " + controller); etc!

I just did a little test case, running from a main that starts with an Application.launch(...) and, just like it says in the doc, that doesn't return and the code after it doesn't get executed.

Maybe you should put the following code (lines 7-9) in your start method or init method?.

I did, I managed to get the program running without error by calling the controller directly (sceneController.total....) however the program stops responding immediately.

    private static void tick()
    {
        long lastTime = System.nanoTime();
        final double amtOfTicks = 100;
        double ns = 1000000000 / amtOfTicks;
        double delta = 0;
        while(running)
        {
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            if(delta >= 1)
            {
                update();
                delta--;
            }
        }
    }

    private static void update()
    {
        sceneController.totalGoldLabel.setText(Float.toString(game.getTotalGold()));
        //controller.currentGoldLabel.setText(Float.toString(game.getCurGold()));
        //controller.clickCountLabel.setText(Integer.toString(game.getClickCount()));
    }

    @Override
    public void start(Stage primaryStage) {
        try {
            VBox page = (VBox) FXMLLoader.load(GoldMiner.class.getResource("GoldMiner.fxml"));
            Scene scene = new Scene(page);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception ex) {
            Logger.getLogger(GoldMiner.class.getName()).log(Level.SEVERE, "", ex);
        }

        game = new Game();
        running = true;
        tick();
    }

}

Maybe because you never finish the start method? (It calls tick() which never returns).

Anyway, that while loop in tick() looks very wrong to me - depending on what update() does that's just going to melt the CPU.

I tried moving all the code from the tick inside the start method which didnt do anything.

EDIT: I managed to get it working, however my values are not updating on the GUI.

GoldMiner.java

package com.github.geodox.goldminer;

import java.util.logging.Level;
import java.util.logging.Logger;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import com.github.geodox.goldminer.game.Game;

public class GoldMiner extends Application
{
    public static Game game;
    static long lastTime = System.nanoTime();
    static double ns = 1000000000 / 100;
    static double delta = 0;

    public static void main(String[] args)
    {
        Application.launch(GoldMiner.class, (java.lang.String[])null);
    }

    private static void update()
    {
        sceneController.totalGoldLabel.setText(Float.toString(game.getTotalGold()));
        sceneController.currentGoldLabel.setText(Float.toString(game.getCurGold()));
        sceneController.clickCountLabel.setText(Integer.toString(game.getClickCount()));
    }

    private static void mainLoop()
    {
        game = new Game();

        if(sceneController.game == null)
            sceneController.game = game;

        long currTime = System.nanoTime();
        delta += (currTime - lastTime) / ns;
        lastTime = currTime;
        if(delta >= 1)
        {
            update();
            delta--;
        }
    }

    @Override
    public void start(Stage primaryStage) {
        try {
            VBox page = (VBox) FXMLLoader.load(GoldMiner.class.getResource("GoldMiner.fxml"));
            Scene scene = new Scene(page);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception ex) {
            Logger.getLogger(GoldMiner.class.getName()).log(Level.SEVERE, "", ex);
        }
        mainLoop();
    }

}

sceneController.java

package com.github.geodox.goldminer;

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

import com.github.geodox.goldminer.game.Game;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;

public class sceneController {

    public static Game game;

    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;

    @FXML
    public static Label totalGoldLabel;

    @FXML
    private Button startAll;

    @FXML
    public Label miningStatus;

    @FXML
    public Label totalMinersLabel;

    @FXML
    private Button clickMine;

    @FXML
    public static Label clickCountLabel;

    @FXML
    private Button save;

    @FXML
    public Label perClickGoldLabel;

    @FXML
    private Button buyMiner;

    @FXML
    public Label currentGoldStatus;

    @FXML
    private Button stopAll;

    @FXML
    private Button load;

    @FXML
    public static Label currentGoldLabel;

    @FXML
    public Label perSecondGoldLabel;

    @FXML
    private Font x1;

    @FXML
    private Color x2;

    @FXML
    private Font x3;

    @FXML
    private Color x4;

    @FXML
    void initialize() {
        assert totalGoldLabel != null : "fx:id=\"totalGoldLabel\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert startAll != null : "fx:id=\"startAll\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert miningStatus != null : "fx:id=\"miningStatus\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert totalMinersLabel != null : "fx:id=\"totalMinersLabel\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert clickMine != null : "fx:id=\"clickMine\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert clickCountLabel != null : "fx:id=\"clickCountLabel\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert save != null : "fx:id=\"save\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert perClickGoldLabel != null : "fx:id=\"perClickGoldLabel\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert buyMiner != null : "fx:id=\"buyMiner\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert currentGoldStatus != null : "fx:id=\"currentGoldStatus\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert stopAll != null : "fx:id=\"stopAll\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert load != null : "fx:id=\"load\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert currentGoldLabel != null : "fx:id=\"currentGoldLabel\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert perSecondGoldLabel != null : "fx:id=\"perSecondGoldLabel\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert x1 != null : "fx:id=\"x1\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert x2 != null : "fx:id=\"x2\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert x3 != null : "fx:id=\"x3\" was not injected: check your FXML file 'GoldMiner.fxml'.";
        assert x4 != null : "fx:id=\"x4\" was not injected: check your FXML file 'GoldMiner.fxml'.";

        clickMine.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                game.addGold(game.getPerClickGold());
                game.addClickCount();
            }
        });

        save.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {

            }
        });

        load.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {

            }
        });

        startAll.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {

            }
        });

        stopAll.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {

            }
        });

        buyMiner.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {

            }
        });

    }
}

Game.java

package com.github.geodox.goldminer.game;

public class Game
{
    protected float totalGold;
    protected float curGold;
    protected float perSecGold;
    protected float perClickGold;
    protected int clickCount;

    public Game()
    {
        totalGold = 0;
        curGold = 0;
        perSecGold = 1;
        perClickGold = 1;
        clickCount = 0;
    }

    public void addGold(float goldValue)
    {
        this.curGold += goldValue;
        this.totalGold += goldValue;
    }

    public void removeGold(float goldValue)
    {
        this.curGold -= goldValue;
    }

    public float getTotalGold()
    {
        return totalGold;
    }

    public float getCurGold()
    {
        return curGold;
    }

    public float getPerSecGold()
    {
        return perSecGold;
    }

    public void setPerSecGold(float perSecGold)
    {
        this.perSecGold = perSecGold;
    }

    public void addPerSecGold(float perSecGold)
    {
        this.perSecGold += perSecGold;
    }

    public float getPerClickGold()
    {
        return perClickGold;
    }

    public void setPerClickGold(float perClickGold)
    {
        this.perClickGold = perClickGold;
    }

    public void addPerClickGold(float perClickGold)
    {
        this.perClickGold += perClickGold;
    }

    public void addClickCount()
    {
        this.clickCount += 1;
    }

    public int getClickCount()
    {
        return this.clickCount;
    }

}

You still have exactly the same problems I described in my previous post:
tick() contains an infinite loop that just runs at 100% CPU usage
start() never finishes because it calls tick() which never returns.

tick() seems to be trying to scheduling regular updates - if so a loop is the worst way to do it. Better to use a Timer to schedule regular calls, or maybe there's something in JavaFX itself that's like a Swing Timer.

Alright, so I removed the loop completely. I implemented a SwingTimer

    Timer timer;
    ActionListener listener;

    listener = new ActionListener()
    {
        public void actionPerformed(ActionEvent e) {
            if(sceneController.game == null)
                sceneController.game = game;
            update();
        }
    };

    timer = new Timer(1000, listener);
    timer.setInitialDelay(1000);
    timer.start();

However, It will not update at all anymore. It seems that the timer just isn't working. Is it because I put it into the start method?

Does start return after the program has started, back to the main method? Or ONLY when the program is closed?

start returns when it has executed all the code you put in it. It's Application.launch that never returns.

Where exactly did you put the code to start the Timer?
Did you try a print in the update() method to confirm unambiguously whether it's being called?

Okay, and I put it in the start method.
I did, and nothing.

I even tried putting the ActionListener and Timer outside of the start method, and just called timer.start(); inside the start, also initializing the timer in there aswell.

EDIT:
Got it working with java.util.Timer; and Platform.runLater();, apparently if you touch any FX Component you must use Platform.runLater(); and since I am not using swing for GUI, whats the point in using it if I found that Util Timer works?

Yes, there's no reason for Swing Timer when you're using JavaFX, so your solution is correct. There must be a JavaFX equivalent to javax.swing.timer, maybe AnimationTimer or maybe Timeline ??

You can use the AnimationTimer but I chose not to because it compliments dynamic time steps over fixed time steps. I'll check out what Timeline is.

EDIT:
Timeline is used with KeyFrames, although there may be a way, if there is, it probably isn't suitable.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.