2009-10-13 31 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