当前位置: 首页 > 知识库问答 >
问题:

javafx,从另一个线程更新ui

阮星火
2023-03-14

我有一个javafx应用程序和一个通过javafx.concurrent.task实现的工作线程,它执行一个很长的过程,即压缩和上载一组文件。
我已通过ProgressProperty将任务进度连接到进度条。
除此之外,我还希望将正在处理的项的详细状态报告到UI中。即正在处理的文件的名称及其大小和单个文件进程可能产生的任何错误。
不能从辅助线程中使用这些信息更新UI,最多只能将其添加到同步集合中。
但我需要一些事件来通知UI新数据可用。
javafx是否对此问题有特定的支持?

我没有设计一个临时的跨线程机制作为Platform.RunLater,而是尝试允许从其他线程监听每个属性。与Task提供的runningProperty和stateProperty一样

共有2个答案

吴伟志
2023-03-14

这个答案与丹尼尔的答案使用了相同的概念。

附件是来自任务javadoc的部分结果示例的副本(修复了当前嵌入在Java 8 javadoc中的语法错误,并添加了更具体的泛型类型)。您可以对其进行修改。

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

public class PartialResultsTask extends Task<ObservableList<Rectangle>> {
    private ReadOnlyObjectWrapper<ObservableList<Rectangle>> partialResults =
            new ReadOnlyObjectWrapper<>(
                    this, 
                    "partialResults",
                    FXCollections.observableArrayList(
                            new ArrayList<>()
                    )
            );

    public final ObservableList<Rectangle> getPartialResults() {
        return partialResults.get();
    }

    public final ReadOnlyObjectProperty<ObservableList<Rectangle>> partialResultsProperty() {
        return partialResults.getReadOnlyProperty();
    }

    @Override
    protected ObservableList<Rectangle> 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框架。

太叔岳
2023-03-14

我遇到了一个类似的问题,据我所知,您必须自己处理错误处理。我的解决方案是通过方法调用更新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线程进行更新(就像我在其他框架中所做的那样)。

 类似资料:
  • 问题内容: 我有一个javafx应用程序和一个工作线程,通过来实现,它执行一个漫长的过程,即压缩并上传一组文件。 我已通过将任务进度连接到进度条。 除此之外,我想将有关正在处理的项目的详细状态报告到ui中。 也就是说,正在处理的文件的名称及其大小以及单个文件处理可能引起的任何错误。 用这些信息更新UI不能从工作线程中完成,最多我可以将其添加到同步集合中。 但是然后我需要一些事件来通知UI新数据可用

  • 所以我在这个问题上有点卡住了。我有一个非常基本的游戏,你用箭头键在网格周围移动一艘船。 我添加了另一个线程与一些怪物,应该自动漫游网格。我可以从打印语句中看到线程正在运行怪物正在移动,但是,图像位置没有更新。 我发现了一些类似的问题,有很多建议可以使用。但我不确定它是否符合我的具体情况,如果符合,如何实施。 下面是怪物类正在做的事情,每秒将怪物向右移动一个空间。就像我提到的,每次调用时,我都会记录

  • 问题内容: 亲爱的大家,我遇到了挥杆相关的问题。由于违反公司政策,我无法共享代码,因此我将尽力解释该问题。 简而言之,我创建了一个扩展包含JLabel的JWindow的类。JLabel的文本是通过计时器对象随机更新的,该计时器对象使用scheduleAtFixedRate方法每50毫秒实例化一个TimerTask。JLabel中的值是通过在一个单独的线程(称为传输线程)中调用一个方法来检索的,该线

  • 问题内容: 在我的Java应用程序中,当调用主模块时,我在单独的线程中启动SWT GUI。我需要在主线程中执行一些长时间的操作并更新GUI线程。当我尝试从主线程更新GUI线程(即更改标签文本等)时,出现了。根据我在线阅读的内容,因为SWT不允许非UI线程更新UI对象。如何从主线程更新GUI线程。 我在网上找到了一些示例,但是它们都处理了GUI在主线程中运行并且长时间操作在单独的线程中的情况。我的情

  • 问题内容: 我想更改Android中的UI。 我的主类创建第二个类,然后第二个类调用主类的方法。主类中的方法应更新UI,但程序在运行时会崩溃。 我该怎么办? 我的主要班级: 还有我的第二堂课: 问题答案: 您不能从主线程以外的线程调用UI方法。您应该使用Activity#runOnUiThread()方法。

  • 我正在尝试使用来自另一个实现的类。我的所有GUI都在一个类中(我的文本区域就在这个类中),我正在创建一个线程,并在创建GUI时运行它。我正在尝试使用