1

I'm fairly new to JavaFX, and I'm building a GUI game. I coded the logic of the game before in Java, and now I'm trying to integrate it with SceneBuilder. This doubt may be very basic and obvious, but I can't seem to understand where I'm going wrong.

I have to create a timer label on my SceneBuilder canvas, that pulls the time from the java code and updates that on the GUI. This timer isn't a regular timer, which is why I can't just use a clock in my controller. I have to use the value I get from the Java code. Here it is:

FXML Controller file:

public class SampleController implements Initializable {

    public SampleController getSampleController(){
        return this;
    }

@FXML private Label displayTime;

@FXML
public void updatePage(String data){
    displayTime.setText(data);
}

@FXML
private void handleStartGameA1(ActionEvent event) throws InterruptedException{
System.out.println("Game has been started!");
World w = new World();
w.runGame();
}

FXML file:

  <Label id="displayTime" fx:id="displayTime" layoutX="381.0" layoutY="125.0" prefHeight="23.0" prefWidth="301.0">
     <font>
         <Font size="18.0" />
     </font>
  </Label>

Java file:

public class World {
    public static Clock WorldClock; // Clock class only to get the custom time

    public World(){
        WorldClock = new Clock();
        public void runGame() throws InterruptedException{
        for (int minute=0; minute<=WorldProperty.MaxMinutes/10; minute++){

        // irrelevant code

        FXMLLoader fxmlLoader = new FXMLLoader();
        SampleController sc = new SampleController();
        sc.getSampleController();
        sc.updatePage(WorldClock.getTime());
        }
    }
}

The Runtime Error:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Node.fireEvent(Node.java:8413)
    at javafx.scene.control.Button.fire(Button.java:185)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:417)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769)
    ... 45 more
Caused by: java.lang.NullPointerException
    at javafxapplication1.SampleController.updatePage(SampleController.java:41)
    at World.World.runGame(World.java:102)
    at javafxapplication1.SampleController.handleStartGameA1(SampleController.java:52)
    ... 55 more

What could be going wrong? I feel I'm being unconventional by creating a SampleController constructor, but I've gathered that it works from online resources. Also, in the updatePage(String data) function, if I don't update the label and simply print a statement System.out.println("The time is: " + data);, it works perfectly well. This leads me to believe that for some reason the label is not getting updated correctly. What can I do to resolve this?

user2918532
  • 11
  • 1
  • 4
  • Possible duplicate of [What is a NullPointerException, and how do I fix it?](http://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – fabian May 05 '17 at 14:01

1 Answers1

0

You don't load the FXML, so the UI components, including the label, don't get created, and you don't connect the controller to the FXML loader.

You need something like

FXMLLoader fxmlLoader = new FXMLLoader();
SampleController sc = new SampleController();
fxmlLoader.setController(sc);
fxmlLoader.setLocation(getClass().getResource("path/to/file.fxml"));
Parent root = fxmlLoader.load();
// display root somewhere...
James_D
  • 201,275
  • 16
  • 291
  • 322
  • My issue is, the Java file I'm putting this code in, does not have any root/scene/stage. Those components have been declared in yet another java document using `public class JavaFXApplication1 extends Application {`. Do I necessarily need to have a stage in this Java document too? I'm using 2 java documents because as I said, I wrote the code earlier so it's not been integrated with JavaFX. – user2918532 May 05 '17 at 14:14
  • Well, no. Presumably you are actually already loading the FXML file *and displaying its contents* somewhere. You need to get the reference to the controller when you do that. Else you just have a reference to another instance of the controller class (in which, as you have discovered, the `@FXML`-annotated fields are not initialized). – James_D May 05 '17 at 14:39
  • Right, I understand. Could you elaborate more on how to get a reference to the controller, rather than get a reference to an instance of the controller? – user2918532 May 05 '17 at 14:54
  • Just do exactly what I posted at the point in the code where you load and display the FXML file. Then `sc` will be a reference to the actual controller that is controlling the displayed UI (not a reference to another instance of the same class, which is what you have in your code). – James_D May 05 '17 at 14:56