我正在編寫一個JavaFX應用程序,它可以在套接字上接收數據點並實時顯示它們。問題是JavaFX渲染速度太慢。我有一個Swing實現,運行速度夠快,但我需要使用JavaFX。我應該使用什麼方法來處理JavaFX Canvas多線程?
,我中工作的制約因素有:
- 爲可視化的控制只能通過JavaFX應用程序線程(我相信這是必需的所有JavaFX和Swing應用程序)進行更新。
- 可視化應該從人眼的角度來平滑地更新。每秒大約10次更新就足夠了。每秒一次都不夠。
- 傳入的數據速率足夠高(每秒大約50個事件,在其他上下文中並不高),並且每個事件處理都足夠昂貴,以至於必須在JavaFX應用程序以外的線程中接收和處理傳入數據線程,以便GUI不會阻塞(我相信對於許多GUI應用程序來說這是一種常見的需求)。
到目前爲止,我的方法是使用Canvas JavaFX節點作爲可視化控件,接收線程調度Canvas的更新以稍後在JavaFX應用程序線程中運行,就像這樣。
public void onEvent(Event event) {
....do processing...
Platform.runLater(new Runnable() {
@Override
public void run() {
graphics.setFill(...);
graphics.fillRect(...);
}});
}
我想到了幾個辦法,可能加快這的:
- 使用WritableImage而不是爲可視化的畫布。缺點是WritableImage/PixelWriter似乎沒有很多繪圖方法,例如它甚至沒有fillRect。我想我將不得不實施我自己的版本,我的版本可能會變慢。
- 讓Canvas對象擁有處理傳入數據的線程。從該畫布複製到作爲JavaFX應用程序線程場景圖形中節點的畫布。該副本可能會沿着這些行的代碼
sceneCanvas.getGraphicsContext2D().drawImage(processingCanvas.snapshot(SnapshotParameters(), null) 0, 0);
完成。這樣做的缺點是我認爲它不是線程安全的,並且快照調用似乎相對昂貴。 - 渲染到處理傳入數據的線程中的AWT BufferedImage,然後使用SwingFXUtils.toFXImage()從BufferedImage複製到畫布。這樣做的缺點是線程語義看起來不太清楚,使用AWT看起來有點愚蠢。
你能提出一些潛在的方法嗎?
謝謝!
您可以在處理線程中創建FX畫布,然後將其交給FX應用程序線程(通過Platform.runLater)以交換場景圖中的「舊」畫布。 – isnot2bad 2014-09-29 09:57:48
您是否已經測量了您的畫布繪製方法運行的時間? – isnot2bad 2014-09-29 09:58:47
繪圖方法相對較快,通常少於一毫秒。我發現最大的問題是代碼使用了Platform.runLater()。增加每個Platform.runLater()調用中完成的工作可顯着提高應用程序的吞吐量。我不確定這個問題是否是Platform.runLater()的開銷,或者問題是JavaFX是否將脈衝調用與Platform.runLater()調用交錯,從而導致更多的重繪。我仍然很好奇人們認爲對於這樣的應用來說,這是一個很好的架構方法。謝謝! – 2014-09-29 18:41:37