2014-01-23 78 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

相關問題