Using JFreeChart to display recent changes in a time series

后端 未结 3 1915
陌清茗
陌清茗 2020-11-21 10:56

How can I use JFreeChart to display just the most recent data in a continually updated time series?

Addenda: A complete, working example that incorporates the accept

相关标签:
3条回答
  • 2020-11-21 11:45

    You can also eliminate the zero by first advanceTime(), then appendData. (swap the way they are doing it in the example).

    0 讨论(0)
  • 2020-11-21 11:49

    The JFreeChart class DynamicTimeSeriesCollection is a good choice.

    Addendum: As noted by @Bahadır, the last point of the series was persistently zero. @Don helpfully suggests advancing the time and then appending the data.

    dataset.advanceTime();
    dataset.appendData(newData);
    

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.EventQueue;
    import java.awt.FlowLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Random;
    import javax.swing.JButton;
    import javax.swing.JComboBox;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import org.jfree.chart.ChartFactory;
    import org.jfree.chart.ChartPanel;
    import org.jfree.chart.JFreeChart;
    import org.jfree.chart.axis.ValueAxis;
    import org.jfree.chart.plot.XYPlot;
    import org.jfree.data.time.DynamicTimeSeriesCollection;
    import org.jfree.data.time.Second;
    import org.jfree.data.xy.XYDataset;
    import org.jfree.ui.ApplicationFrame;
    import org.jfree.ui.RefineryUtilities;
    
    /** @see http://stackoverflow.com/questions/5048852 */
    public class DTSCTest extends ApplicationFrame {
    
        private static final String TITLE = "Dynamic Series";
        private static final String START = "Start";
        private static final String STOP = "Stop";
        private static final float MINMAX = 100;
        private static final int COUNT = 2 * 60;
        private static final int FAST = 100;
        private static final int SLOW = FAST * 5;
        private static final Random random = new Random();
        private Timer timer;
    
        public DTSCTest(final String title) {
            super(title);
            final DynamicTimeSeriesCollection dataset =
                new DynamicTimeSeriesCollection(1, COUNT, new Second());
            dataset.setTimeBase(new Second(0, 0, 0, 1, 1, 2011));
            dataset.addSeries(gaussianData(), 0, "Gaussian data");
            JFreeChart chart = createChart(dataset);
    
            final JButton run = new JButton(STOP);
            run.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    String cmd = e.getActionCommand();
                    if (STOP.equals(cmd)) {
                        timer.stop();
                        run.setText(START);
                    } else {
                        timer.start();
                        run.setText(STOP);
                    }
                }
            });
    
            final JComboBox combo = new JComboBox();
            combo.addItem("Fast");
            combo.addItem("Slow");
            combo.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    if ("Fast".equals(combo.getSelectedItem())) {
                        timer.setDelay(FAST);
                    } else {
                        timer.setDelay(SLOW);
                    }
                }
            });
    
            this.add(new ChartPanel(chart), BorderLayout.CENTER);
            JPanel btnPanel = new JPanel(new FlowLayout());
            btnPanel.add(run);
            btnPanel.add(combo);
            this.add(btnPanel, BorderLayout.SOUTH);
    
            timer = new Timer(FAST, new ActionListener() {
    
                float[] newData = new float[1];
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    newData[0] = randomValue();
                    dataset.advanceTime();
                    dataset.appendData(newData);
                }
            });
        }
    
        private float randomValue() {
            return (float) (random.nextGaussian() * MINMAX / 3);
        }
    
        private float[] gaussianData() {
            float[] a = new float[COUNT];
            for (int i = 0; i < a.length; i++) {
                a[i] = randomValue();
            }
            return a;
        }
    
        private JFreeChart createChart(final XYDataset dataset) {
            final JFreeChart result = ChartFactory.createTimeSeriesChart(
                TITLE, "hh:mm:ss", "milliVolts", dataset, true, true, false);
            final XYPlot plot = result.getXYPlot();
            ValueAxis domain = plot.getDomainAxis();
            domain.setAutoRange(true);
            ValueAxis range = plot.getRangeAxis();
            range.setRange(-MINMAX, MINMAX);
            return result;
        }
    
        public void start() {
            timer.start();
        }
    
        public static void main(final String[] args) {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    DTSCTest demo = new DTSCTest(TITLE);
                    demo.pack();
                    RefineryUtilities.centerFrameOnScreen(demo);
                    demo.setVisible(true);
                    demo.start();
                }
            });
        }
    }
    
    0 讨论(0)
  • 2020-11-21 11:50

    One alternative approach to @thrashgod's answer would be to use TimeSeriesCollection and setting item age on the TimeSeries. Below code can setup a graph to show last 1 hour of data with 1 minute intervals.

    private TimeSeriesCollection dataset;
    private TimeSeries sensorSeries;
    sensorSeries = new TimeSeries("name", Minute.class);
    sensorSeries.setMaximumItemAge(60);
    dataset = new TimeSeriesCollection();
    dataset.addSeries(sensorSeries);
    

    ..and you will add the data as it comes with:

    sensorSeries.add(new Minute(new Date()), newData);
    
    0 讨论(0)
提交回复
热议问题