2009-10-13 73 views
2

我正在使用JFreeChart繪製多個TimeSeries圖表。它似乎工作正常,但截至今日,所有圖表似乎閃爍,並隨機擾動,使他們無法看到。如果我最小化和最大化,則問題會在幾秒內得到修復,直到下次更新或鼠標單擊。有人對這個問題有什麼想法嗎?使用JFreeChart進行毛刺圖形繪製

alt text

的代碼非常簡單:

TimeSeries ts = new TimeSeries("Graph", Millisecond.class); 
TimeSeriesCollection dataset = new TimeSeriesCollection(ts); 
JFreeChart Graph = createChart(dataset); 
ChartPanel panel_Graph = new ChartPanel(Graph); 

.... 

JFrame newWindow = new JFrame("Graph"); 
newWindow.setLayout(new GridLayout()); 
newWindow.setContentPane(panel_Graph); 
newWindow.setMinimumSize(new Dimension(600, 480)); 
newWindow.setLocationRelativeTo(null); 
newWindow.setVisible(true); 


static private JFreeChart createChart(TimeSeriesCollection dataset) { 
     JFreeChart chart = ChartFactory.createTimeSeriesChart(
      "Graph", 
      "Time", 
      "Value", 
      dataset, 
      false, 
      true, 
      false 
     ); 
     final XYPlot plot = chart.getXYPlot(); 
     ValueAxis timeaxis = plot.getDomainAxis(); 
     timeaxis.setAutoRange(true); 
     timeaxis.setFixedAutoRange(60000.0); 
     return chart; 
} 
+0

爲什麼你將XYPlot標記爲最終? – Koekiebox 2009-10-13 13:22:31

+0

嗯,這只是嘗試在互聯網上嘗試解決問題的不同解決方案所剩餘的。刪除它沒有區別。 – thodinc 2009-10-13 13:54:05

回答

0

你是如何添加的數據點圖表?你是在AWT事件調度線程上做的嗎?您應該使用SwingUtilities.invokeAndWait。你可以使用invokeLater,但是如果你的程序忙於做其他事情,GUI可能不會及時更新。

此外,你有多少個數據點? I discovered,對於大量數據點,固定自動量程的代碼效率非常低。這可能在最新版本中已經修復(我不知道)。

+0

那麼,我有一個單獨的線程,接收來自另一個節點的消息,並將該double值添加到系列中: ts.addOrUpdate(new Millisecond(),Update); 在一種情況下,新的數據點每10秒鐘到達一次,而另一個則每秒鐘最多5次。但是,兩者似乎都遇到了同樣的問題。 – thodinc 2009-10-13 13:39:39

+0

此外,在間隔10s的更新情況下,第一個數據點不會顯示,直到第二個數據點到達,然後這兩個點都可見。 – thodinc 2009-10-13 13:43:04

+0

接收消息的線程需要將時間序列更新放到Event Dispatch Thread中。我建議使用SwingUtilities.invokeLater來防止您的I/O線程在UI更新時被阻塞。 – Adamski 2009-10-13 13:50:27

1

如果您看到不一致/損壞的圖像,它有時會指示更新事件調度線程以外的線程上的數據集。我建議你添加一些assert語句來驗證這一點:

assert SwingUtilities.isEventDispatchThread();

另外,請注意,JFreeChart不是特別有效,因爲無論何時添加新數據點,它都會重新呈現整個圖形。您可以在此處進行的一項優化如下:

  • 如果您的應用程序包含多個圖表,則只會爲當前顯示的圖表傳播DatasetChangeEvent。如果圖表被隱藏(例如在不同的選項卡上),那麼只需記錄它已過時的事實,並在選擇選項卡時需要重新渲染。

編輯

基於丹的響應,它聽起來就像你的I/O線程接收消息也更新JFreeChart的數據集,而實際上更新應該在事件指派線程進行您的評論(並且消息應該在單獨的I/O線程上執行)。爲了達到這個目的,我建議你使用一種基於節流的方法,將I/O事件放在一起。您可以使用BlockingQueue來實現此目的;例如

// Message definition containing update information. 
public interface Message { ... } 

// BlockingQueue implementation used to enqueue updates received on I/O thread. 
BlockingQueue<Message> msgQ = ... 

// Method called by I/O thread when a new Message is received. 
public void msgReceived(Message msg) { 
    boolean wasEmpty = msgQ.isEmpty(); 

    msgQ.add(msg); 

    // Queue was empty so need to re-invoke Swing thread to process queue. 
    if (wasEmpty) { 
    // processUpdates is a re-useable Runnable defined below. 
    SwingUtilities.invokeLater(processUpdates); 
    } 
} 

// Runnable that processes all enqueued events. Much more efficient than: 
// a) Creating a new Runnable each time. 
// b) Processing one Message per call to run(). 
private final Runnable processUpdates = new Runnable() { 
    public void run() { 
    Message msg; 

    while ((msg = msgQ.poll) != null) { 
     // Add msg to dataset within Event Dispatch thread. 
    } 
    } 
} 
+0

我已經把斷言SwingUtilities.isEventDispatchThread();正好在數據集在接收到消息後被更新的點之上,並且它似乎沒有任何區別。 此外,似乎如果我點擊圖表(沒有拖動或任何東西),問題變得更糟。 http://i18.photobucket.com/albums/b115/thodinc/jfreebug.jpg – thodinc 2009-10-13 13:49:44

+0

現在,我只是打開一個新的JFrame來顯示圖形,但標籤的想法聽起來也不錯。但是,即使只打開一個圖形,也會出現此問題。即使我轉移到較舊版本的代碼,它也不會像以前那樣發生並現在發生。 – thodinc 2009-10-13 13:52:11

+0

儘管您的消息處理實現比我所做的更有效,但它似乎對圖形部分沒有任何影響。我用invokeLater使用了LinkedBlockingQueue,並且仍然在使用損壞的圖形。 – thodinc 2009-10-13 15:49:45