0

I've created a visualizer in JavaFX for a problem I'm solving, and currently I can get it to show up after the calculations in my application are done, but I would like the window to first be opened and then run the calculations, so I can animate the visualization during the computations.

This is the code for creating an instance of the problem, showing the visualizer and performing the calculations:

public static void run(Visualizer v) {
    readInput();
    if (v != null) {
        v.resizeCanvas(rectangles);
        v.drawAllRectangles(rectangles);
        v.show();
    }
    calculateArea();

    System.out.println(totalArea);
}

The Visualizer class extends javafx.application.Application and utilizes a JavaFX Canvas. calculateArea() simply runs a static method which performs some calculations.

What currently happens when I run my program is:

  1. It waits for input on stdin
  2. The computations are run
  3. The visualization is displayed

What I want:

  1. It waits for input on stdin
  2. The visualization is displayed
  3. The computations are run

So for some reason the displaying of the visualization is delayed even though I call v.show() before calculateArea().

My first hunch would be to run the calculations in a new thread, but according to the documentation "The JavaFX scene graph, which represents the graphical user interface of a JavaFX application, is not thread-safe and can only be accessed and modified from the UI thread also known as the JavaFX Application thread."

I tried putting a Thread.sleep(3000) right after v.show(), and what happened was that my program just waited 3 seconds before running calculateArea() followed by the window being displayed.

Thanks for any input!

Axel Kennedal
  • 443
  • 5
  • 16
  • 4
    The Task and Service classes are probably what you're looking for: https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm – Selim Mar 23 '18 at 10:43
  • You're right, thanks a bunch! – Axel Kennedal Mar 23 '18 at 11:04
  • Have a look at [this question](https://stackoverflow.com/questions/30249493/using-threads-to-make-database-requests), which is about accessing databases; you can use the same techniques to run your calculation in the background. – James_D Mar 23 '18 at 11:22

1 Answers1

1

You should call your calculation method in a separate thread (as suggested by @Selim) launched in the applications start() method.

If your calculation method directly changes graphical content on screen (which it should not do BTW...) you need to pass this graphics code (not the calculation itself) to Platform.runLater().

Timothy Truckle
  • 12,232
  • 2
  • 22
  • 44
  • I see. I understand that it's not the best to mix in graphics code into the calculation code, my idea was to just have a boolean flag to enable/disable running any eventual graphics instructions within the calculation code but I guess that's not a great way to solve it. Thanks for the feedback :) – Axel Kennedal Mar 23 '18 at 11:03
  • @AxelKennedal *"I understand that it's not the best to mix in graphics code into the calculation code,"* Yes, it violates the *Separation of concerns / Single Responsibility* Pattern (SoC/SRP). Have a look at the *MVVM/MVVC* Pattern. JavaFX has been designed to support that. – Timothy Truckle Mar 23 '18 at 11:06