JavaFX 动画折线图


package harika;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

public class ChartWork extends Application {
private static final int MAX_DATA_POINTS = 50;
private int xSeriesData = 0;
private XYChart.Series<Number, Number> series1 = new XYChart.Series<>();
private XYChart.Series<Number, Number> series2 = new XYChart.Series<>();
private XYChart.Series<Number, Number> series3 = new XYChart.Series<>();
private ExecutorService executor;
private ConcurrentLinkedQueue<Number> dataQ1 = new ConcurrentLinkedQueue<>();
private ConcurrentLinkedQueue<Number> dataQ2 = new ConcurrentLinkedQueue<>();
private ConcurrentLinkedQueue<Number> dataQ3 = new ConcurrentLinkedQueue<>();
private NumberAxis xAxis;
private void init(Stage primaryStage) {
    xAxis = new NumberAxis(0, MAX_DATA_POINTS, MAX_DATA_POINTS / 10);
    xAxis.setForceZeroInRange(false);
    xAxis.setAutoRanging(false);
    xAxis.setTickLabelsVisible(false);
    xAxis.setTickMarkVisible(false);
    xAxis.setMinorTickVisible(false);
    NumberAxis yAxis = new NumberAxis();
    // Create a LineChart
    final LineChart<Number, Number> lineChart = new LineChart<Number, Number>(xAxis, yAxis) {
        // Override to remove symbols on each data point
        @Override
        protected void dataItemAdded(Series<Number, Number> series, int itemIndex, Data<Number, Number> item) {
        }
    };
    lineChart.setAnimated(false);
    lineChart.setTitle("Animated Line Chart");
    lineChart.setHorizontalGridLinesVisible(true);
    // Set Name for Series
    series1.setName("Series 1");
    series2.setName("Series 2");
    series3.setName("Series 3");
    // Add Chart Series
    lineChart.getData().addAll(series1, series2, series3);
    primaryStage.setScene(new Scene(lineChart));
}

@Override
public void start(Stage stage) {
    stage.setTitle("Animated Line Chart Sample");
    init(stage);
    stage.show();

    executor = Executors.newCachedThreadPool(new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setDaemon(true);
            return thread;
        }
    });
    AddToQueue addToQueue = new AddToQueue();
    executor.execute(addToQueue);
    //-- Prepare Timeline
    prepareTimeline();
}
private class AddToQueue implements Runnable {
    public void run() {
        try {
            // add a item of random data to queue
            dataQ1.add(Math.random());
            dataQ2.add(Math.random());
            dataQ3.add(Math.random());
            Thread.sleep(500);
            executor.execute(this);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}
//-- Timeline gets called in the JavaFX Main thread
private void prepareTimeline() {
    // Every frame to take any data from queue and add to chart
    new AnimationTimer() {
        @Override
        public void handle(long now) {
            addDataToSeries();
        }
    }.start();
}
private void addDataToSeries() {
    for (int i = 0; i < 20; i++) { //-- add 20 numbers to the plot+
        if (dataQ1.isEmpty()) break;
        series1.getData().add(new XYChart.Data<>(xSeriesData++, dataQ1.remove()));
        series2.getData().add(new XYChart.Data<>(xSeriesData++, dataQ2.remove()));
        series3.getData().add(new XYChart.Data<>(xSeriesData++, dataQ3.remove()));
    }
    // remove points to keep us at no more than MAX_DATA_POINTS
    if (series1.getData().size() > MAX_DATA_POINTS) {
        series1.getData().remove(0, series1.getData().size() - MAX_DATA_POINTS);
    }
    if (series2.getData().size() > MAX_DATA_POINTS) {
        series2.getData().remove(0, series2.getData().size() - MAX_DATA_POINTS);
    }
    if (series3.getData().size() > MAX_DATA_POINTS) {
        series3.getData().remove(0, series3.getData().size() - MAX_DATA_POINTS);
    }
    // update
    xAxis.setLowerBound(xSeriesData - MAX_DATA_POINTS);
    xAxis.setUpperBound(xSeriesData - 1);
}
public static void main(String[] args) {
    launch(args);
}
}

所以我有这个代码,我在网上找到了它。我正在尝试阅读此代码并了解它的作用。我知道javaFX并理解它的这一部分,但我还不知道其他部分。但在我需要确保我可以使这个动画更流畅之前。然后我可以详细介绍..

我没有设法找出如何做到这一点。我应该怎么做才能让它更顺畅?

要从示例中获取流畅的动画,请执行以下操作:

  • MAX_DATA_POINTS50 更改为 2_500
  • Thread.sleep(500)更改为Thread.sleep(10)

如果您每秒只更新图表两次(如您发布的示例所示(,则动画将跳跃。

如果每秒更新 30+ 次,动画将很流畅。 人眼通常以每秒 30+ 帧的速度记录为平滑动画,以较小的帧到帧变化。 请参阅维基百科"帧速率和人类视觉"。


一般来说,如果您无法通过查看其代码来很好地理解它的工作原理和功能,我会警告不要使用您在互联网上找到的此类代码示例。 具体而言,您提供的示例代码在多个线程上执行。 如果您的需求不需要在多个线程上执行,那么您可能不应该使用这样的解决方案。

相关内容

  • 没有找到相关文章

最新更新