JavaFX SwingWorker 等价物?
Posted
技术标签:
【中文标题】JavaFX SwingWorker 等价物?【英文标题】:JavaFX SwingWorker Equivalent? 【发布时间】:2015-03-06 02:36:18 【问题描述】:是否有与 Java SwingWorker 类等效的 JavaFX?
我知道 JavaFX Task 但您只能发布字符串消息或进度。我只想在 GUI 线程中调用一个方法,就像我对 SwingWorker 所做的那样(通过发布任意类型的消息)。
这是我的意思的一个例子:
class PrimeNumbersTask extends
SwingWorker<List<Integer>, Integer>
PrimeNumbersTask(JTextArea textArea, int numbersToFind)
//initialize
@Override
public List<Integer> doInBackground()
while (! enough && ! isCancelled())
number = nextPrimeNumber();
publish(number);
setProgress(100 * numbers.size() / numbersToFind);
return numbers;
@Override
protected void process(List<Integer> chunks)
for (int number : chunks)
textArea.append(number + "\n"); // HERE: execute in GUI thread
解决方案
非常感谢您的回答。我正在寻找的解决方案是使用Platform.runLater(Runnable guiUpdater)。
【问题讨论】:
【参考方案1】:我会重写你的SwingWorker
如下:
class PrimeNumbersTask extends Task<List<Integer>>
PrimeNumbersTask(TextArea textArea, int numbersToFind)
// initialize
@Override
protected List<Integer> call() throws Exception
while (!enough && !isCancelled())
number = nextPrimeNumber();
updateMessage(Integer.toString(number));
updateProgress(numbers.size(), numbersToFind);
return numbers;
用法:
TextArea textArea = new TextArea();
PrimeNumbersTask task = new PrimeNumbersTask(numbersToFind);
task.messageProperty().addListener((w, o, n)->textArea.appendText(n + "\n"));
new Thread(task).start(); // which would actually start task on a new thread
说明:
是的,我们没有 publish()
方法,就像 JavaFX 中的 SwingWorker
那样,但在您的情况下,使用 updateMessage()
就足够了,因为我们可以为此属性注册一个侦听器并在每个消息更新的时间。
如果这还不够,您可以随时使用Platform.runLater()
来安排 GUI 更新。如果您进行过多的 GUI 更新并且 GUI 线程被拖慢,您可以使用以下成语:Throttling javafx gui updates
【讨论】:
我已经在考虑这个解决方案,但在我看来它更像是一种解决方法(好吧,它适用于主要示例,但并非在所有情况下都适用)。 Platform.runLater() 方法正是我想要的。 您刚刚创建了新的任务实例,并没有启动 PrimeNumbersTask 的任何后台工作。我想需要调用把它放在一个线程上并启动它。否则,如果只是调用 task.run() GUI 被阻止.. 我随意添加缺少的行: new Thread(task).start();让我知道这是否可以【参考方案2】:除了只能传递字符串的updateMessage
方法之外,还有可以传递整个对象的updateValue
方法,所以我相信你可以以类似的方式使用它。 Task 文档的“返回部分结果的任务”部分描述了这种方法。另一种方法是其他答案中也提到的Platform.runLater()
方法。
请注意,这些方法之间的一个重要区别是,第一个方法是合并结果,这意味着对于多个频繁的 updateValue 调用,可能会省略一些方法,以防止 FX 线程泛滥。
另一方面,Platform.runLater 方法将发送所有中间结果,但由于如果您有高频更新会导致 FX 线程泛滥的危险,可能需要一些额外的努力来手动避免它,例如 @eckig在他的回答中建议指向Throttling javafx gui updates
【讨论】:
【参考方案3】:永远不要使用 SwingWorker。 SwingWorker.java 源代码中的这段代码应该足以作为不使用它的参数:
private static final int MAX_WORKER_THREADS = 10;
而是让自己熟悉Executor 以及随之而来的服务。
它与 JavaFX 无关,它只是普通的 Java。但是,您的问题与 JavaFX 有关。这是一个关于如何Update UI in JavaFX Application Thread using Platform.runLater()的示例。
【讨论】:
了解您的不喜欢,但只是想知道SwingWorker
是否实际上没有处理从非 EDT 到 EDT (process
) 的块传输,比创建 Runnable
时的效率略高。时间。查看publish
的源代码,我看到AccumulativeRunnable
实例包含在包sun.swing
中。不知道这意味着什么,作为一个完整的 JavaFX 新手,我不知道我们是否会看到类似的东西......以上是关于JavaFX SwingWorker 等价物?的主要内容,如果未能解决你的问题,请参考以下文章
Linux 上的 JavaFX 显示“图形设备初始化失败:es2,sw”