How to make plots run in seperate thread?

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
statik213
Posts: 6
Joined: Wed May 25, 2005 3:29 am

How to make plots run in seperate thread?

Post by statik213 » Thu Jun 02, 2005 5:49 pm

Hi,
I'd like to have my charts run in a seprate thread from the main application. I'm using the JFreeChart to plot realtime data and sometimes the GUI becomes unresponsive whena chart is being redrawn, if the chart could be redrawn in a seprate thread I could give it lower priority and maintian responsiveness of my App's GUI.

My thoughts were to extend the XYPlot class and overload

public void draw(Graphics2D g2,
Rectangle2D area,
Point2D anchor,
PlotState parentState,
PlotRenderingInfo info)

And use a SwingWorker instance that calls the super's draw method.
Any advice? [/code]

statik213
Posts: 6
Joined: Wed May 25, 2005 3:29 am

Post by statik213 » Thu Jun 02, 2005 6:16 pm

I tried overloading draw and doing the swingworker thing and it failed. It never seemed to be able to completely draw the plot. It drew parts of it but never completely :(
See below:

Code: Select all

    private class ThreadedXYPlot extends XYPlot {
        ThreadedXYPlot(XYDataset dataset,
                       ValueAxis domainAxis,
                       ValueAxis rangeAxis,
                       XYItemRenderer renderer) {
            super(dataset, domainAxis, rangeAxis, renderer);
        }

        public void drawSuper(Graphics2D g2,
                              Rectangle2D area,
                              Point2D anchor,
                              PlotState parentState,
                              PlotRenderingInfo info) {
            super.draw(g2, area, anchor, parentState, info);
        }


        public void draw(final Graphics2D g2,
                         final Rectangle2D area,
                         final Point2D anchor,
                         final PlotState parentState,
                         final PlotRenderingInfo info) {

            final SwingWorker worker = new SwingWorker() {
                public Object construct() {
                    System.out.println("drawing");
                    drawSuper(g2, area, anchor, parentState, info);
                    return null;
                }
            };
            worker.start();
        }
    }
:( :( :( :( :( :( :(

Eduardo Ramalho
Posts: 43
Joined: Fri Mar 14, 2003 3:14 pm
Location: Porto (Portugal)
Contact:

Post by Eduardo Ramalho » Thu Jun 02, 2005 7:40 pm

be redrawn in a seprate thread I could give it lower priority and maintian responsiveness of my App's GUI.
Hi,

In you realtime chart, do you have a hard requirement, that for each new sample, the chart should be refreshed?

I had once the same problem. What I did was collecting the samples in a buffer. I think I used a TimeSeries. This buffer was not used in the chart.

Then, I had a SwingTimer, that for each 5 sec, would copy the buffer, to the XYPlot internal buffer. The chart was automatically redraw at that time with the new samples received in that 5 sec interval.

Hope that helps,

Eduardo

statik213
Posts: 6
Joined: Wed May 25, 2005 3:29 am

Post by statik213 » Thu Jun 02, 2005 8:52 pm

Well I am doing that something like that, right now data can arrive at varying intervals the default being 125ms. I have two timeseries that I write to, one is bound to the plot and the other is a buffer that I write the readings to as they come in. I don't use a timer as I will be getting readings in a steady stream and will in effect be a timer itself. I keep track of when I last updated the plot's TimeSeries and make sure I update it after a fixed amount of time has passed (default 500 ms).

skunk

Post by skunk » Thu Jun 02, 2005 10:01 pm

(Un)fortunately its part of the design of swing that all drawing MUST take place on the event dispatching thread.

JFreeChart isn't really designed to do this. As previously stated, the entire chart is redrawn whenever data changes. Most charts that have real time display capabilities only need to redraw the 2 most recent datapoints. a.k.a. "the hard-right-edge"

That being said, check to see how many times the chart is being repainted whenever you update anything. You might find that there are many more redundant repaints than you expect. My performance improved greatly when I bracketed the code that caused repaints to happen with the following:

Code: Select all

chart.setNotify(false);

// update data
// update axes
// update legends
// etc etc etc

chart.setNotify(true);
You still need a timer,or at least some way to limit the frequency of updates. A Greenspan surprise rate hike can generate an amazing amount of data...

statik213
Posts: 6
Joined: Wed May 25, 2005 3:29 am

Post by statik213 » Thu Jun 02, 2005 11:27 pm

skunk wrote:(Un)fortunately its part of the design of swing that all drawing MUST take place on the event dispatching thread.

JFreeChart isn't really designed to do this. As previously stated, the entire chart is redrawn whenever data changes. Most charts that have real time display capabilities only need to redraw the 2 most recent datapoints. a.k.a. "the hard-right-edge"

That being said, check to see how many times the chart is being repainted whenever you update anything. You might find that there are many more redundant repaints than you expect. My performance improved greatly when I bracketed the code that caused repaints to happen with the following:

Code: Select all

chart.setNotify(false);

// update data
// update axes
// update legends
// etc etc etc

chart.setNotify(true);

You still need a timer,or at least some way to limit the frequency of updates. A Greenspan surprise rate hike can generate an amazing amount of data...
Well, I was doing something like what you were doing but using two timeseries so that I would change the timeseries only once causing only one repaint, but your approach is better. I changed my code to handle updates like this.

Still, I'm updating the screen every 500 ms and at some points need to have 4 plot windows working and updating twice a second...

The program is reponsive but I'd like it to feel more fluid. Is there anyway of forcing the draw()'s to run in a seperate thread?

Locked