javafx,从另一个线程更新ui

我有一个javafx应用程序,以及一个通过javafx.concurrent.Task实现的工作线程,它执行一个漫长的过程,即压缩和上传一组文件。
我已经通过progressProperty将任务进度连接到进度条。
除此之外,我想要一个关于正在处理的项目的详细状态,以便报告给ui。 也就是说,正在处理的文件的名称及其大小以及单个文件进程可能产生的任何错误。
使用这些信息更新UI无法从工作线程完成,最多可以将其添加到同步集合中。
但后来我需要一些事件来通知UI新数据可用。
javafx是否对此问题有一些特定的支持?

更新,更好的配方

我没有将特设的跨线程机制设计为Platform.runLater,而是试图允许从其他线程中侦听每个属性。 就像Task提供的runningProperty和stateProperty一样

我遇到了类似的问题,据我所知,你必须自己处理error handling。 我的解决方案是通过方法调用更新UI:

就像是:

  try { //blah... } catch (Exception e) { reportAndLogException(e); } ... public void reportAndLogException(final Throwable t) { Platform.runLater(new Runnable() { @Override public void run() { //Update UI here } }); } 

基本上我只是手动将其移回UI线程进行更新(正如我在其他任何框架中所做的那样)。

这个答案使用了与Daniel的答案相同的概念。

附上一份来自Task javadoc的Partial Result示例的副本(针对当前嵌入在Java 8 javadoc中的语法错误进行了修复,并添加了更具体的Generic类型)。 您可以使用它的修改。

将您的例外放在partialResults集合中。 对于您的情况,您不需要从任务返回exception列表,而是可以将它们放在显示exception的某个UI控件中(例如带有CellFactoryListView用于exception显示)。 请注意,partialResults集合不需要同步,因为它始终在JavaFX UI线程上更新和访问(更新通过类似于Daniel的解决方案的Platform.runLater()调用进行)。

 public class PartialResultsTask extends Task> { private ReadOnlyObjectWrapper> partialResults = new ReadOnlyObjectWrapper<>( this, "partialResults", FXCollections.observableArrayList( new ArrayList<>() ) ); public final ObservableList getPartialResults() { return partialResults.get(); } public final ReadOnlyObjectProperty> partialResultsProperty() { return partialResults.getReadOnlyProperty(); } @Override protected ObservableList call() throws Exception { updateMessage("Creating Rectangles..."); for (int i = 0; i < 100; i++) { if (isCancelled()) break; final Rectangle r = new Rectangle(10, 10); r.setX(10 * i); Platform.runLater(() -> partialResults.get().add(r)); updateProgress(i, 100); } return partialResults.get(); } } 

更新它的可观察属性时,任务首先检查FX应用程序线程上是否发生了更新。 如果是,它会立即更新。 如果不是,则将更新包装在Platform.runLater()调用中。 请参阅任务源代码以了解如何完成此操作。

也许可以定义一组通用的并发感知属性,但JavaFX并没有提供这样的设施。 实际上,它并不需要。 除了javafx.concurrent包之外,JavaFX是一个单线程UI框架。