2014-01-23 150 views
2

我想在TimeSeries图表上显示实时数据,其中实时显示在x轴上(或至少有速度的时间与实时相同)。JFreeChart - 如何在TimeSeries图表的X轴上实时显示

下面是随机数字作为实时输入问题的SSCCE。在x轴上示出的时间比实时(假设它被示出为hh:mm:ss的格式):快得多

public class DynamicTimeSeriesChart extends JPanel { 

    private DynamicTimeSeriesCollection dataset; 
    private JFreeChart chart = null; 

    public DynamicTimeSeriesChart(final String title) { 

     dataset = new DynamicTimeSeriesCollection(1, 2000, new Second()); 
     dataset.setTimeBase(new Second(0, 0, 0, 1, 1, 1990)); // date 1st jan 0 mins 0 secs 

     dataset.addSeries(new float[1], 0, title); 
     chart = ChartFactory.createTimeSeriesChart(
      title, "Time", title, dataset, true, 
      true, false); 
     final XYPlot plot = chart.getXYPlot(); 

     ValueAxis axis = plot.getDomainAxis(); 
     axis.setAutoRange(true); 
     axis.setFixedAutoRange(200000); // proportional to scroll speed 
     axis = plot.getRangeAxis(); 

     final ChartPanel chartPanel = new ChartPanel(chart); 
     setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); 
     add(chartPanel); 
    } 

    public void update(float value) { 
     float[] newData = new float[1]; 
     newData[0] = value; 
     dataset.advanceTime(); 
     dataset.appendData(newData); 
    } 

    public static void main(String[] args) { 
     JFrame frame = new JFrame("testing"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     final DynamicTimeSeriesChart chart = new DynamicTimeSeriesChart("random numbers"); 
     frame.add(chart); 
     frame.pack(); 
     frame.setVisible(true); 
     Timer timer = new Timer(100, new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       EventQueue.invokeLater(new Runnable() { 
        @Override 
        public void run() { 
         chart.update((float) (Math.random() * 10)); 
        } 
       }); 
      } 
     }); 
     timer.start(); 
    } 
} 

回答

4

尽管可以接受的是sleep()initial thread,摇摆GUI对象应在事件调度线程上构建和操作只有。而应使用javax.swing.Timer来调整更新,如here所示。 100 ms的delay将以大约10 Hz的频率更新。

如果漂移不可接受,则以另一个线程以名义速率的一半轮询主机的时钟并使用EventQueue.invokeLater()更新数据集。确保主机已同步到NTP服务器。

附录:根据您的更新,注意所有 Swing GUI的对象必须构造和操作只有事件调度线程上,不只是javax.swing.Timer。 Swing Timer的优势在于它在EDT上触发。下面的变化显示大约实时10秒的1Hz数据。

附录:您可以调整传递给setTimeBase()的时间,如here所示。

image

import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.text.SimpleDateFormat; 
import javax.swing.JFrame; 
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.DateAxis; 
import org.jfree.chart.plot.XYPlot; 
import org.jfree.data.time.DynamicTimeSeriesCollection; 
import org.jfree.data.time.Second; 

/** 
* @see https://stackoverflow.com/a/21307289/230513 
*/ 
public class DynamicTimeSeriesChart extends JPanel { 

    private final DynamicTimeSeriesCollection dataset; 
    private final JFreeChart chart; 

    public DynamicTimeSeriesChart(final String title) { 
     dataset = new DynamicTimeSeriesCollection(1, 1000, new Second()); 
     dataset.setTimeBase(new Second(0, 0, 0, 23, 1, 2014)); 
     dataset.addSeries(new float[1], 0, title); 
     chart = ChartFactory.createTimeSeriesChart(
      title, "Time", title, dataset, true, true, false); 
     final XYPlot plot = chart.getXYPlot(); 
     DateAxis axis = (DateAxis) plot.getDomainAxis(); 
     axis.setFixedAutoRange(10000); 
     axis.setDateFormatOverride(new SimpleDateFormat("ss.SS")); 
     final ChartPanel chartPanel = new ChartPanel(chart); 
     add(chartPanel); 
    } 

    public void update(float value) { 
     float[] newData = new float[1]; 
     newData[0] = value; 
     dataset.advanceTime(); 
     dataset.appendData(newData); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       JFrame frame = new JFrame("testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       final DynamicTimeSeriesChart chart 
        = new DynamicTimeSeriesChart("Alternating data"); 
       frame.add(chart); 
       frame.pack(); 
       Timer timer = new Timer(1000, new ActionListener() { 
        private boolean b; 

        @Override 
        public void actionPerformed(ActionEvent e) { 
         chart.update(b ? 1 : 0); 
         b = !b; 
        } 
       }); 
       timer.start(); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 
+0

我已经改变了SSCCE代码来使用你的定时器和EventQueue.invokeLater()提出的。但问题仍然存在。我不会如何“轮询主机的时钟”或“确保主机与NTP服务器同步”。我不知道如何设置图表的时间。 –

+0

对您的附录的评论:您的示例图表似乎以实时的速度显示时间,但是当我将计时器的速率更改为1 Hz以外的任何速度时,图表会以不同的速度显示时间。我希望图表能够以实际速度显示时间,而不考虑数据更新速率。感谢您迄今的努力。 –

+0

实时是1赫兹;您可能能够合并以不同速率到达的活动。 – trashgod

相关问题