1秒間に何百回も更新されるJava FX 2アプリがあります。ラベルがほんの一瞬だけ部分的に空白になるという問題が発生していますが、これはかなり頻繁に発生します。これを修正するにはどうすればよいですか?
1 に答える
Platform.runLater()を 1 秒間に何百回も呼び出すのは得策ではありません。Platform.runLater() を呼び出して UI を更新する前に、データ ソースの入力速度を調整するか、データをまとめてバッチ処理し、Platform.runLater が 1 秒間に 30 回以上呼び出されないようにすることをお勧めします。
Platform.runLater 呼び出しに関するドキュメントを改善し、基盤となるプラットフォームに優れた runLater イベント スロットリング システムを実装することを検討するために、jira リクエストRT-21569を提出しました。
runLater イベントをバッチ処理するためのサンプル ソリューションは、このフォーラム スレッドで Richard Bair によって提供されています。
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.stage.Stage;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Semaphore;
/**
*
*/
public class BackgroundLoadingApp extends Application {
private ListView<String> listView;
private List<String> pendingItems;
private Semaphore lock = new Semaphore(1);
protected void addItem(String item) throws InterruptedException {
if (Platform.isFxApplicationThread()) {
listView.getItems().add(item);
} else {
// It might be that the background thread
// will update this title quite frequently, and we need
// to throttle the updates so as not to completely clobber
// the event dispatching system.
lock.acquire();
if (pendingItems == null) {
pendingItems = new LinkedList<String>();
pendingItems.add(item);
Platform.runLater(new Runnable() {
@Override public void run() {
try {
lock.acquire();
listView.getItems().addAll(pendingItems);
pendingItems = null;
} catch (InterruptedException ex) {
ex.printStackTrace();
} finally {
lock.release();
}
}
});
} else {
pendingItems.add(item);
}
lock.release();
}
}
/**
* The main entry point for all JavaFX applications.
* The start method is called after the init method has returned,
* and after the system is ready for the application to begin running.
* <p/>
* <p>
* NOTE: This method is called on the JavaFX Application Thread.
* </p>
*
* @param primaryStage the primary stage for this application, onto which
* the application scene can be set. The primary stage will be embedded in
* the browser if the application was launched as an applet.
* Applications may create other stages, if needed, but they will not be
* primary stages and will not be embedded in the browser.
*/
@Override public void start(Stage primaryStage) throws Exception {
listView = new ListView<String>();
primaryStage.setScene(new Scene(listView));
primaryStage.show();
// Start some background thread to load millions of rows as fast as it can. But do
// so responsibly so as not to throttle the event thread
Thread th = new Thread() {
@Override public void run() {
try {
for (int i=0; i<2000000; i++) {
addItem("Item " + i);
if (i % 200 == 0) {
Thread.sleep(20);
}
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
};
th.setDaemon(true);
th.start();
}
public static void main(String[] args) {
launch(args);
}
}
参照されたフォーラム スレッドからコピーされた Richard Bair によるコメント:
これは、大量のデータを生成する長時間実行スレッドをシミュレートする例です。私はそれが私の好みではうまく機能していないことに気づきました。Thread.sleep が欠落している場合でも、プロセスを圧倒します (おそらく、この場合、同時実行を処理している方法です)。また、「2」ミリ秒のスリープに減らすと、スクロールバーのつまみをつかんで移動できなくなることもわかりました。ここでの問題は、プレス アンド ドラッグのイベント キューにマウス イベントがあることだと思いますが、ドラッグ イベントの間に新しい項目がリストに追加され、サムが移動します。これは、私のドラッグ イベントよりも頻繁に発生するため、サム私が望むところに行くことは決してありません。これは、行数に基づいて親指の位置を処理する方法によるものだと思いますが、