限制javafx gui更新 [英] Throttling javafx gui updates
问题描述
我随机地以高频率接收数据对象,并且需要使用这些来更新JavaFX GUI。但是,我不想用大量的runnables填充javafx事件队列(我使用Platform.RunLater)。
I receive data objects at random times at a high frequency, and need to update the JavaFX GUI with these. However, I don't want to fill the javafx event queue with a very large number of runnables (I use Platform.RunLater).
我一直在考虑如何最好实现限制算法。
I have been thinking of how to best implement a throttling algorithm.
- 最好有一个单独的GUIUpdater线程来检查新对象的阻塞队列,以及然后睡觉例如30ms,然后再次检查,在无限循环中?在这种情况下,阻塞队列是否是最佳数据结构?请注意我只需要最新的数据对象而且blockingQueue是一个FIFO队列,我似乎无法选择最新的条目。
- 或者 - 只是更新才会更好如果nanoTime-startTime> 30ms,使用Platform.RunLater的GUI?在这种情况下,我不需要单独的线程来执行Platform.RunLater调用。但是 - 如果在30ms未通过时收到更新,然后一段时间内未收到任何更新,则最后一次更新将不会显示在GUI中。
关于如何以简短有效的方式为JavaFX Platform.RunLater GUI更新设计限制算法的任何建议?
Any suggestions on how to design a throttling algorithm for JavaFX Platform.RunLater GUI updates in a short, efficient way?
推荐答案
这是 任务
用于实现 updateMessage(...)$ c $的类c>方法和其他类似方法。它提供了一个漂亮,强大的解决方案,以避免泛滥FX应用程序线程:
This is the idiom used in the Task
class for implementing the updateMessage(...)
method, and other similar methods. It provides a nice, robust solution to avoid flooding the FX Application Thread:
import java.util.concurrent.atomic.AtomicLong;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ThrottlingCounter extends Application {
@Override
public void start(Stage primaryStage) {
final AtomicLong counter = new AtomicLong(-1);
final Label label = new Label();
final Thread countThread = new Thread(new Runnable() {
@Override
public void run() {
long count = 0 ;
while (true) {
count++ ;
if (counter.getAndSet(count) == -1) {
updateUI(counter, label);
}
}
}
});
countThread.setDaemon(true);
countThread.start();
VBox root = new VBox();
root.getChildren().add(label);
root.setPadding(new Insets(5));
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 150, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
private void updateUI(final AtomicLong counter,
final Label label) {
Platform.runLater(new Runnable() {
@Override
public void run() {
final String msg = String.format("Count: %,d", counter.getAndSet(-1));
label.setText(msg);
}
});
}
public static void main(String[] args) {
launch(args);
}
}
AtomicLong
保存用于更新Label的当前值。计数不断增加并更新 AtomicLong
,但仅调度对 Platform.runLater(...)
的调用它的当前值是-1。 Platform.runLater(...)
使用中的当前值更新
并将标签
AtomicLong AtomicLong
翻转回-1,表示它已准备好进行新的更新。
The AtomicLong
holds the current value to be used to update the Label. The count continually increments and updates the AtomicLong
, but only schedules a call to Platform.runLater(...)
if it's current value is -1. The Platform.runLater(...)
updates the Label
with the current value from the AtomicLong
and flips the AtomicLong
back to -1, indicating that it's ready for a new update.
这里的效果是在FX应用程序线程准备好处理它们时安排对 Platform.runLater(...)
的新调用。没有硬编码的时间间隔可能需要调整。
The effect here is to schedule new calls to Platform.runLater(...)
whenever the FX Application Thread is ready to handle them. There's no hard-coded time interval which could need tuning.
这篇关于限制javafx gui更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!