Javafx Updating UI from a Thread without direct calling Platform.runLater

后端 未结 2 579

Nowadays some says it is not suitable to use Platform.runLater() for updating the UI from a non-JavaFX Thread and Oracle site introduce a way with bindings for

相关标签:
2条回答
  • 2021-01-14 00:25

    As updateMessage() on a Task finally uses Platform.runLater() to update the messageProperty, it is no alternative to a direct runLater() in your code. So the essence is:

    JavaFX is not multithreaded, any Porperty binding will only work if the property is modified in the JavaFX thread, e.g. by using Platform.runLater().

    0 讨论(0)
  • 2021-01-14 00:37

    I don't think it's quite true to say it's not "suitable" to use Platform.runLater(...) to update the UI from a background thread. There are certainly cases where that is the correct thing to do, as shown in the Task Javadocs. What the javafx.concurrent API provides is a "higher-level" interface to the functionality you commonly need when you are writing multithreaded JavaFX applications. The classes in this package are written by people with a lot of expertise in multithreaded programming, so it's likely that they have accounted for subtleties that the average programmer may not be aware of.

    As an example, while it is correct that updateMessage eventually ends up calling Platform.runLater(...), the two are not completely equivalent. If you try the same thing with a naïve call to 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 UI will become (at least partially) unresponsive. The reason is that you're scheduling so many Runnables on the FX Application thread, it doesn't have time to do its regular work (rendering UI, responding to user input, etc). The implementation of updateMessage(...) is carefully written to "throttle" the calls to Platform.runLater(...) (it basically limits them to one per frame-rendering). That code is a little tricky to implement: using the javafx.concurrent API as in your code example means you don't have to implement it yourself.

    So changes to the UI must always be made on the FX Application Thread, and the way to schedule those changes is via Platform.runLater(...). In effect you either call that directly, or call code that ends up calling it. However, some of the API methods that wrap the calls to Platform.runLater(...) do so in quite sophisticated ways, and when those methods provide the functionality you need, you should probably prefer those to making the calls yourself.

    0 讨论(0)
提交回复
热议问题