4

I'm coding a Scene that represents the main menu of my JavaFX program;

This Scene also uses a background working Thread that every 1-2 seconds spawns a Shape and makes it translate from left to right using a TranslateTransition, and removes it when the animation is complete;

My problem is that "rarely" this Exception is thrown, but I can't undestand why because it doesn't seem to be a problem in one of my Class:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:344)
    at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:506)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:745)
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
...
Continuously printing this until I close the program.

Does someone have an idea?

EDIT: Here's the code, I had to reduce it from 1380 lines to around 100, I hope it was worth the time ahah!

import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import static ExceptionMain.Status.NEW;

public class ExceptionMain extends Application {

    public enum Status {NEW, RUNNING, FINISHED}

    public static void main(String[] args) {launch(args);}

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setScene(new Main_Menu().menu_Scene);
        primaryStage.show();
    }

    class Main_Menu {
        Main_Menu() {
            panel = new Pane();
            ram_List = new ArrayList<>();
            indexes = new ArrayList<>();
            wait_Time = -1;
            menu_Scene = new Scene(panel, 720, 250);

            Thread thread = new Thread(() -> {
                try {
                    while (!Thread.currentThread().isInterrupted()) {
                        ram_List.add(new Random_Animation_Manager());
                        for (int i = ram_List.size() - 1; i >= 0; i--) {
                            if (ram_List.get(i).status == NEW) {
                                try {
                                    ram_List.get(i).run();
                                    wait_Time = ram_List.get(i).wt;
                                } catch (InterruptedException ignored) {}
                            } else if (ram_List.get(i).status == Status.FINISHED)
                                indexes.add((short) i);
                        }
                        indexes.forEach(index -> ram_List.remove(ram_List.get(index)));
                        indexes.clear();
                        Thread.sleep(wait_Time);
                    }
                } catch (InterruptedException ignored) {}
            });
            thread.setDaemon(true);
            thread.start();
        }

        Scene menu_Scene;
        Pane panel;
        List<Random_Animation_Manager> ram_List;
        List<Short> indexes;
        short wait_Time;

        class Random_Animation_Manager {

            Random_Animation_Manager() {status = NEW;}

            TranslateTransition tt;
            Shape shape;
            short wt;
            volatile Status status;

            void run() throws InterruptedException {
                status = Status.RUNNING;
                Random ram = new Random();
                wt = (short) (1 + ram.nextInt(5));

                shape = new Circle(10);
                shape.setLayoutX(-150);
                shape.setLayoutY((short) (1 + ram.nextInt(250)));
                shape.setFill(Color.ORANGE);
                tt = new TranslateTransition(Duration.millis(4000), shape);
                tt.setToX(920);

                CountDownLatch wait_For_Platform_Operation = new CountDownLatch(1);
                Platform.runLater(() -> {
                    panel.getChildren().add(shape);
                    wait_For_Platform_Operation.countDown();
                });
                wait_For_Platform_Operation.await();

                tt.setOnFinished(event -> {
                    panel.getChildren().remove(shape);
                    status = Status.FINISHED;
                });
                tt.play();
            }
        }
    }
}

You can imagine my real code is very different, I simplified a lot of things trying to be left with the main Characters!

As you can see, my background thread creates a Random_Animation_Manager that puts in a list;

He then checks for every elements of the list, and if it's in a NEW state, it runs the object that spawns the Shape, if it's in the FINISH state, it stores the index of the Object to be deleted; In the ends, it waits for a while (the time value is randomly created in the Object and passed to the thread) and the loop continues.

I hope someone can tell me what's the problem, I even speeded up the "deployment time" so you should get the error faster!

I'm still "new" to JavaFX programming and concurrency, I hope I can learn something from this!

Dea5
  • 131
  • 1
  • 9
  • 1
    where's your code ? – dumbPotato21 May 16 '17 at 20:06
  • I'm thinking of a way of posting it because It's easy to undestand but relatively long. – Dea5 May 16 '17 at 20:09
  • 1
    then make sure nothing is null. Follow the stacktrace. If it is long, then believe me, no one is going to read through all of it. – dumbPotato21 May 16 '17 at 20:10
  • I know, I wrote here simply to know if someone has never had an error like this... – Dea5 May 16 '17 at 20:12
  • 4
    You cannot update the UI from a background thread. You probably have a race condition somewhere that is causing the exception. – James_D May 16 '17 at 20:21
  • Well, what you're describing in words shouldn't be a long code, perhaps 50 lines. Remember that we don't need any decorations. – user1803551 May 16 '17 at 20:23
  • Done! Sorry but I couldn't go below 100 lines :P – Dea5 May 16 '17 at 21:22
  • I... don't undestand the duplicate tag, my question is about the Exception and why I'm getting it without sending me to a line in my classes: also, my "wait" is different every loop, so I think a Timeline is useless because it has a fixed waitTime (?) – Dea5 May 16 '17 at 21:44
  • 1
    At the time I closed it, from the (limited) information that was provided in the question, the linked question appeared to be a duplicate. There is too much code for me to be able to read on a phone - when I am back at a computer I will look and reopen if it is different. – James_D May 16 '17 at 23:21
  • Thanks for your time! – Dea5 May 16 '17 at 23:22
  • I'll reopen, but the basic idea still holds: you don't need a thread to perform animations. You can create a single `Timeline` with `KeyFrame`s at arbitrary timepoints, for example. Or you could create a collection of `SequentialTransition`s, each containing a `PauseTransition` for a specified time followed by your `TranslateTransition`s, and put them all in a `ParallelTransition`. Or just use an `AnimationTimer`... – James_D May 17 '17 at 00:46
  • FWIW this doesn't throw any exceptions when I run it... Is the stack trace you posted coming from the example code you posted? – James_D May 17 '17 at 00:51
  • Yes. I modified the code and speeded up things, maybe you should get the error faster... I really don't undestand, I'm quite sure It should work fine, I use a CountDownLatch that waits for the Platform operation, and simply set a remove when the animation is finished. – Dea5 May 17 '17 at 07:58
  • 3
    Solved, I found the problem: the run() method is called in another Thread, and doesn't inizialize and start the animations in a runLater(); This caused some of the animation to be null, and when trying to remove the shape from the panel in the setOnFinished() method, a NPE is thrown. – Dea5 May 17 '17 at 16:11
  • 1
    Just ran into this problem using a Timeline outside the FX thread. Would love to see a full explanation of why this problem occurs... maybe I will dig into it and provide an explanation – wrslatz Dec 20 '17 at 20:43

0 Answers0