Javafx从线程更新UI,而不直接调用Platform.runLater [英] Javafx Updating UI from a Thread without direct calling Platform.runLater

查看:5601
本文介绍了Javafx从线程更新UI,而不直接调用Platform.runLater的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在有人说,不适合使用 Platform.runLater()从非JavaFX线程更新UI和Oracle网站介绍一种使用绑定进行进度的方法条更新。在这里我想更新一个标签,所以这样编码:

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 progress bar updating. Here I want to update a Label, so 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();

它可以工作。

知道是不够好还是有任何其他方式来考虑?
谢谢。

I want to know is it good enough or is there any other ways to consider? Thank you.

推荐答案

我认为这不是真的, code> Platform.runLater(...)从后台线程更新UI。有一些情况下,这是正确的事情,如显示在 任务 Javadocs 。当您编写多线程JavaFX应用程序时, javafx.concurrent API提供的是一个更高级的接口,用于您通常需要的功能。这个包中的类是由具有许多多线程编程专业知识的人编写的,所以很可能他们已经解决了一般程序员可能不知道的细微之处。

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.

作为一个例子,虽然 updateMessage 最终最终调用 Platform.runLater(...) ,两者不完全等价。如果你尝试一个天真的调用 Platform.runLater(..)

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);

您的UI将变为(至少部分)无响应。原因是你在FX应用程序线程上安排了太多的 Runnable ,它没有时间做正常的工作(渲染UI,响应用户输入,等)。 updateMessage(...)的实现被仔细写入以调节对 Platform.runLater(...)(基本上将它们限制为每帧渲染一个)。该代码是有点棘手的实现:使用 javafx.concurrent API在你的代码示例意味着你不必自己实现。

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.

因此,对UI的更改必须始终在FX应用程序线程上进行,计划这些更改的方式是通过 Platform.runLater(...)。实际上,您可以直接调用,或调用代码来调用它。然而,一些API方法包装对 Platform.runLater(...)的调用以相当复杂的方式进行,当这些方法提供您需要的功能,你应该更喜欢那些自己打电话。

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.

这篇关于Javafx从线程更新UI,而不直接调用Platform.runLater的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆