2015-01-08 67 views
8

是否存在与Java SwingWorker类相当的JavaFX?JavaFX SwingWorker Equivalent?

我知道JavaFX Task,但是您只能发布String消息或进度。我只想在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)

回答

7

我会重写你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()法作为SwingWorker在JavaFX中,但在你身上r case使用updateMessage()就足够了,因为我们可以向此属性注册侦听器,并在每次更新消息时追加一个新行。

如果这还不够,您总是可以使用Platform.runLater()安排GUI更新。如果你正在做太多的GUI更新和GUI线程正在放缓,您可以用下面的习惯:Throttling javafx gui updates

+0

我已经在想这个解决方案,但在我看来更像是一个解决方法(好吧,它适用于主要的例子,但不是在任何情况下)。 Platform.runLater()方法正是我所期待的。 – Crine

+0

您刚刚创建了任务的新实例,并未启动PrimeNumbersTask的任何后台工作。我想有人需要把它放在一个线程上并启动它。否则,如果你只是调用task.run()图形用户界面被阻止..我觉得可以添加缺失的行:new Thread(task).start();让我知道如果这是好的 – Ewoks

-1

永远不要使用SwingWorker。这在SwingWorker.java源代码段应该是足够的论据不使用它:

private static final int MAX_WORKER_THREADS = 10; 

而是让自己熟悉Executor,并与它一起到来的服务。

它与JavaFX无关,它只是普通的Java。但是,您的问题与JavaFX有关。这里是一个关于如何Update UI in JavaFX Application Thread using Platform.runLater()的例子。

+0

感谢您的Platform.runLater()示例代码:) – Crine

+0

了解您的不喜欢,但只是想知道“SwingWorker”是否实际上可能不会处理从非EDT到EDT('process')块的传输,比创建时每次都有一个'Runnable'。浏览'publish'的源代码,我看到一个'AccumulativeRunnable'实例在'sun.swing'包中。不知道这意味着什么,作为一个完整的JavaFX新手,我不知道我们是否可以看到任何可比较的东西...... –

0

除了updateMessage方法,你只能传递一个字符串,有updateValue方法,你可以通过一个完整的对象,所以我相信你可以以类似的方式使用它。在Task文档的“返回部分结果的任务”部分中描述了该方法。另一种方法是在其他答案中提到的Platform.runLater()方法。

请注意,这些方法之间的一个重要区别是,第一个方法是合并结果,这意味着对于多个频繁updateValue调用,可能会省略一些以防止溢出FX线程。

另一方面,平台。runLater的方法会发送所有的中期结果,但由于外汇线程泛滥的危险,如果你有高频更新,可能需要一些额外的努力来手动避免它,如@eckig在他的答案中指出的Throttling javafx gui updates