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?

1

1 Answer 1

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...
Sign up to request clarification or add additional context in comments.

4 Comments

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.
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).
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?
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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.