Javafx Updating UI from thread without calling Platform.runLater directly

Currently, some say that it is Platform.runLater()

not recommended to use the binding method to update the execution string to update the UI from a non-JavaFX thread and an Oracle site. Here I want to update the Label, so I coded it like this:

Task task = new Task() {
    @Override
    protected Object call() throws Exception {
        int i = 0;
        while (true) {
            this.updateMessage("Count " + i);
            System.out.println(i);
            // Thread.sleep(10);
            i++;
        }
    }
};

Thread t = new Thread(task);
lbStatus.textProperty().bind(task.messageProperty());
t.start();

      

He works.

I want to know if this is good or are there any other ways to consider? Thank.

+3


source to share


2 answers


I don't think this is true, that it is "inappropriate" to use Platform.runLater(...)

to update the UI from a background thread. There are of course cases where this is the right thing to do, as shown in the Task

Javadocs
. What the javafx.concurrent

API provides is a "higher level" interface to the functions you typically need when writing multithreaded JavaFX applications. The classes in this package are written by people with extensive experience in multithreaded programming, so they probably took into account subtleties that the average programmer might not know about.

As an example, while it is correct updateMessage

to end up with a call Platform.runLater(...)

, they are not completely equivalent. If you try the same thing with a naive call Platform.runLater(..)

:

// Don't do this! It will make the UI unresponsive:
Task task = new Task() {
    @Override
    protected Object call() throws Exception {
        int i = 0;
        while (true) {
            Platform.runLater(() -> lblStatus.textProperty().set("Count "+i));
            i++;
        }
        return null ;
    }
};
Thread t = new Thread(task);

      



your user interface will become (at least partially) unresponsive. The reason is that you are scheduling so much Runnable

in the FX application thread, it doesn't have time to do its normal work (rendering the UI, responding to user input, etc.). The implementation is updateMessage(...)

carefully written to "throttle" the calls on Platform.runLater(...)

(it basically restricts them to one to render the frame). This code is a bit tricky to implement: using an API javafx.concurrent

like your example code means you don't have to implement it yourself.

Therefore, changes to the UI should always be done on the FX application thread, and the way to schedule those changes is through Platform.runLater(...)

. In fact, you either call it directly or you call the code that ultimately calls it. However, some of the API methods that wrap calls to Platform.runLater(...)

do so in rather complex ways, and when those methods provide the functionality you need, you probably prefer them to make the calls themselves.

+2


source


Since updateMessage () in the Task finally uses Platform.runLater () to update the messageProperty, this is not an alternative to direct runLater () in your code. So, the gist is this:



JavaFX is not multi-threaded, any Porperty binding will only work if the property is changed in the JavaFX thread, eg. using Platform.runLater ().

0


source







All Articles