2015-01-08 65 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