JavaFx Обновление LineChart в реальном времени - PullRequest
0 голосов
/ 07 декабря 2018

На основе примера JewelSea на AnimatedAreaChart , я разрабатываю это решение для создания линейного графика в реальном времени, но я не знаю, как обновить набор данных (параллельная очередь)из другого потока.Может быть, решение может быть очень простым, но я замерз слишком много.

ПРОСТОЙ ГЛАВНЫЙ:

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

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

    }
}

ЗДЕСЬАнимированная диаграмма

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


    }

1 Ответ

0 голосов
/ 11 декабря 2018

Ну, я усложняю свою жизнь ...

найденное решение:

только что создал геттер для

private ArrayList> dataQs = new ArrayList> ();

, так что с помощью простого внешнего потока можно обновить параллельную структуру.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...