There is a thread that performs large calculations, and after collecting all the data, they need to be displayed in the UI, but at the same time, while the thread is running, the interface gets a stake because of the while loop that waits for the thread to finish, to start displaying information on the graphs.

Here is the startup code:

@FXML void Start() throws UnsupportedFlavorException, InterruptedException, IOException { Programm p = new Programm(); GlobalConstants gc = new GlobalConstants(); Indicator.setVisible(true); p.ReadFrame(); while (true) { synchronized (gc) { if (gc.flag == 3) { labelPredict.setText(String.valueOf(String.format("%.3f", gc.predict * 1000)) + "мм"); ChartSpeedSetter(); ChartCoordSetter(); ChartCoordPDSetter(); ChartSpeedPDSetter(); //ChartLeftFrimeSetter(); Indicator.setVisible(false); break; } } } } 

the Start function is started by the button, then from another class the function is started with the calculations of p.ReadFrame ();

And in while the variable from the stream is synchronized, which at the end of the work sets the flag = 3, while while the stream is running ReadFrame is needed so that the interface does not get up with a stake, but at the end it fills the graphics.

PS I tried through the task and service, the task cannot change the UI element, or I do it wrong (everywhere there are examples with the ProgressBar update). he just swears at the functions that I pass to him.

2 answers 2

When pressed, your button executes its block of code in the FX stream, which is intended only for changing graphics, hence the program hangs until a long operation is performed. Obviously, a long operation must be moved to another thread. Task, Service, but at least the new Thread for this more than fit. Changes in graphics are really possible only in the FX stream, otherwise you will get the action that you get. To get into the FX thread from anywhere you need to wrap the code in

 Platform.runLater(new Runnable() { @Override public void run() { } }); 

In the run block, you will respectively need the correct copy of the controller class or its variables, which you need to set values. These are some basic principles on simple mechanisms.

    Thank you very much, although I knew about runLater but I inserted it in the wrong place, so he cursed.

     void Start() throws UnsupportedFlavorException, InterruptedException, IOException { Programm p = new Programm(); GlobalConstants gc = new GlobalConstants(); Indicator.setVisible(true); p.ReadFrame(); Task task = new Task<Void>() { @Override public Void call() { while (true) { synchronized (gc) { if (gc.flag == 3) { Platform.runLater(new Runnable() { @Override public void run() { labelPredict.setText(String.valueOf(String.format("%.3f", gc.predict * 1000)) + "мм"); ChartSpeedSetter(); ChartCoordSetter(); ChartCoordPDSetter(); ChartSpeedPDSetter(); //ChartLeftFrimeSetter(); Indicator.setVisible(false); } }); break; } } } return null; } }; new Thread(task).start(); }