views:

584

answers:

2
A: 

How are you adding data points to the chart? Are you doing it on the AWT event dispatch thread? You should probably use SwingUtilities.invokeAndWait. You can use invokeLater but if your program is busy doing other things, the GUI might not be updated promptly.

Also, how many data points do you have? I discovered that the code for fixed auto-range was quite inefficient for large numbers of data points. That may have been fixed in the most recent version (I don't know).

Dan Dyer
Well, I have a separate thread that receives messages from another node and adds the double value to the series:ts.addOrUpdate(new Millisecond(), Update);In one case, a new data point arrives every 10 seconds, whereas in the other, up to 5 times a second. However, both seem to be experiencing the same issue.
thodinc
Additionally, in the case of the updates with 10s intervals, the first data point doesn't show until the second one arrives and then both points are visible.
thodinc
The thread receiving the messages needs to marshall the time series update onto the Event Dispatch Thread. I suggest using SwingUtilities.invokeLater to prevent your I/O thread from blocking while the UI updates.
Adamski
I'm not sure what the problem is exactly because I just ran the program on another computer and it seemed to be fine. Could it be that the library is corrupted?
thodinc
The problem's fixed! It seems there was a conflict with my graphics driver. I added the following flag and there are no issues so far:-Dsun.java2d.opengl=true
thodinc
+1  A: 

If you see an inconsistent / corrupt image it is sometimes indicative of updating the data set on a thread other than the Event Dispatch Thread. I suggest you add some assert statements to verify this:

assert SwingUtilities.isEventDispatchThread();

Also, note that JFreeChart isn't particularly efficient as it re-renders the entire graph whenever a new data point is added. One optimisation you could make here is:

  • If your app consists of multiple charts then only propagate DatasetChangeEvents for the chart currently being displayed. If a chart is hidden (e.g. on a different tab) then simply record the fact that it is stale and needs to be rerendered when the tab is selected.

EDIT

Based on your comment to Dan's response it sounds like your I/O thread receiving messages is also updating the JFreeChart dataset, when in fact the update should be performed on the Event Dispatch Thread (and messages should be performed on a separate I/O thread). To achieve this I suggest you use a throttle based approach whereby I/O events are bucketed together. You could use a BlockingQueue to achieve this; e.g.

// 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.
    }
  }
}
Adamski
I've put assert SwingUtilities.isEventDispatchThread(); right above the point where the data set is updated after receiving a message and it doesn't seem to make any difference.Also, it seems that if I click on the graph (without dragging or anything), the problem becomes worse.http://i18.photobucket.com/albums/b115/thodinc/jfreebug.jpg
thodinc
Right now, I'm simply opening up a new JFrame to display the graphs, but the tabbed idea sounds good too. However, the problem occurs even if only one graph is open. It didn't used to happen earlier and occurs now even if I move to an older version of the code.
thodinc
While your implementation of message processing is much more efficient than what I'd done, it doesn't seem to have any effect on the graphing portion. I've used a LinkedBlockingQueue with invokeLater and am still getting corrupted graphs.
thodinc