首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JavaFx实时LineChart更新

JavaFx实时LineChart更新
EN

Stack Overflow用户
提问于 2018-12-07 23:24:31
回答 1查看 143关注 0票数 0

基于AnimatedAreaChartJewelSea's示例,我详细介绍了用于创建实时折线图的解决方案,但我不知道如何从另一个线程更新数据集(并发队列)。也许解决方案可能很简单,但我被太mutch吓呆了。

简单的MAIN:

代码语言:javascript
复制
package application;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;


public class Tester extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            AnchorPane root = (AnchorPane)FXMLLoader.load(getClass().getResource("Monitor.fxml"));
            Scene scene = new Scene(root);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

这里是fxml的基本控制器

代码语言:javascript
复制
package application;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.AnchorPane;


public class MonitorController implements Initializable {

    @FXML
    private AnchorPane arc_panel;

    AnimatedLineChart sup=new AnimatedLineChart(6,250);

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        arc_panel.getChildren().add(sup.buildLineChart());

    }
}

这里是动画图表

代码语言:javascript
复制
package application;
    import javafx.animation.AnimationTimer;
    import javafx.scene.chart.LineChart;
    import javafx.scene.chart.NumberAxis;
    import javafx.scene.chart.XYChart;

    import java.util.ArrayList;
    import java.util.concurrent.ConcurrentLinkedQueue;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadFactory;


    public class AnimatedLineChart {

        private int MAX_DATA_POINTS = 150;
        private int SENSNUM = 1;
        private int xSeriesData = 0;
        private ArrayList<XYChart.Series<Number, Number>> superiorSeries=new ArrayList<XYChart.Series<Number, Number>>();
        private ArrayList<ConcurrentLinkedQueue<Number>> dataQs=new ArrayList<ConcurrentLinkedQueue<Number>>();

        private ExecutorService executor;

        private NumberAxis xAxis;

        private AnimatedLineChart() {}//rendo costruttore di default privato

        public AnimatedLineChart(int numOfChannels,int maxDataPointsPlotted) {
            MAX_DATA_POINTS=maxDataPointsPlotted;
            SENSNUM=numOfChannels;
        }

        public LineChart<Number, Number> buildLineChart() {

            for (int i=0;i<SENSNUM;i++) {
                XYChart.Series<Number, Number> seriesi = new XYChart.Series<>();
                // Set Name for Series
                seriesi.setName("SupCH"+i+1);
                 // Add Chart Series
                superiorSeries.add(seriesi);

                //PREPARE DATAQ HOLDER
                dataQs.add(new ConcurrentLinkedQueue<Number>());

            }


            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("Superior Channels");
            lineChart.setHorizontalGridLinesVisible(true);


            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();



            lineChart.getData().addAll(superiorSeries);

            return lineChart;

        }




        //-- Timeline gets called in the JavaFX Tester 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<SENSNUM;i++) {
                if (dataQs.get(i).isEmpty()) break;
                superiorSeries.get(i).getData().add(new XYChart.Data<>(xSeriesData++, dataQs.get(i).remove()));
                // remove points to keep us at no more than MAX_DATA_POINTS
                if (superiorSeries.get(i).getData().size() > MAX_DATA_POINTS) {
                    superiorSeries.get(i).getData().remove(0, superiorSeries.get(i).getData().size() - MAX_DATA_POINTS);
                }

            }

            // update
            xAxis.setLowerBound(xSeriesData - MAX_DATA_POINTS);
            xAxis.setUpperBound(xSeriesData - 1);
        }

        private class AddToQueue implements Runnable {
            public void run() {
                try {
                    // add a item of random data to queue

                    dataQs.get(0).add(Math.random()*2d);
                    dataQs.get(1).add(Math.random()*2d);
                    Thread.sleep(500);
                    executor.execute(this);

                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }


    }
EN

回答 1

Stack Overflow用户

发布于 2018-12-11 22:02:36

我把我的生活复杂化了..。

已创建的解决方案:

刚刚为创建了一个getter

private ArrayList> dataQs=new ArrayList>;

因此,可以使用一个简单的外部线程来更新并发结构。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53672414

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档