使用 JFreeChart 在时间序列中显示最近的变化

Posted

技术标签:

【中文标题】使用 JFreeChart 在时间序列中显示最近的变化【英文标题】:Using JFreeChart to display recent changes in a time series 【发布时间】:2011-06-30 05:59:13 【问题描述】:

如何使用JFreeChart 仅显示不断更新的时间序列中的最新数据?

附录:包含已接受答案的完整工作示例显示为here。另请参阅此variation 有两个系列。关于setTimeBase(),另请参见Q&A

【问题讨论】:

【参考方案1】:

JFreeChartDynamicTimeSeriesCollection 是一个不错的选择。

附录:正如@Bahadır 所指出的,该系列的最后一点始终为零。 @Don 很有帮助地建议提前时间并然后附加数据。

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

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.chart.ui.ApplicationFrame;
import org.jfree.chart.ui.UIUtils;

/**
 * @see http://***.com/a/15521956/230513
 * @see http://***.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) 
            @Override
            public Dimension getPreferredSize() 
                return new Dimension(640, 480);
            
        , 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();
                UIUtils.centerFrameOnScreen(demo);
                demo.setVisible(true);
                demo.start();
            
        );
    

【讨论】:

感谢您提供这么好的样本。你知道防止线的最后一点为零的方法吗? @Bahadır:这似乎是advanceTime() 的有意效果。我从来没有使用过不同基线值的用例。有什么想法吗?不要忘记对您认为有用的答案进行投票。 :-) “你最后一次投票这个答案是 4 月 25 日 13:11”我总是这样做。顺便说一句,我通过使用 TimeSeriesCollection 而不是动态的来解决这个问题。然后用 add 替换 dataset.appendData,并为数据集设置生命周期。它提供了几乎相同的功能。 @Bahadır:啊,我明白了;谢谢你,以及替代方法。 @Sundhas 保存图表是一个不同的问题,请为此创建一个新问题。【参考方案2】:

您也可以先通过advanceTime(),然后通过appendData 消除零。 (在示例中交换他们的操作方式)。

【讨论】:

@Bahadır:问得好。当我的答案是唯一的答案时,我接受了它以保持我的速度;但没有得分。接受后,@Don 得到了 +15 的答案,这对我们所有人都有帮助,我得到了 +2 的接受。我称之为双赢双赢! :-) 抱歉,我之前在回复@Sundhas 时忽略了这条评论。 @trashgod 对于未来的读者,如果您的答案被接受,将会更有帮助。困惑了一两分钟,直到我意识到这一个常见问题解答风格的问题,完整的答案如下! @DuncanJones:好点;在问题中更新。正如其他地方引用的那样,我将其作为公认的答案。【参考方案3】:

@thrashgod 回答的另一种方法是使用TimeSeriesCollection 并在TimeSeries 上设置项目年龄。下面的代码可以设置一个图表,以 1 分钟的间隔显示最近 1 小时的数据。

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

..您将添加随附的数据:

sensorSeries.add(new Minute(new Date()), newData);

【讨论】:

另见Q&A。

以上是关于使用 JFreeChart 在时间序列中显示最近的变化的主要内容,如果未能解决你的问题,请参考以下文章

数据库中jfreechart中的散点图

使用 jfreechart 设置相同长度的 ValueAxis

JFreeChart DTSC 上的自定义 X 轴标签

调整JFrame大小后更新JFreeChart / JPanel

如何利用jfreechart生成柱状,饼状,折线形图形。

jfreechart生成饼状图显示数据的百分比