File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Swing / AWT / SWT and the fly likes How do I render and draw buffered Images in Parallel?  - JFreeChart Question Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "How do I render and draw buffered Images in Parallel?  - JFreeChart Question" Watch "How do I render and draw buffered Images in Parallel?  - JFreeChart Question" New topic
Author

How do I render and draw buffered Images in Parallel? - JFreeChart Question

Austin Henggi
Greenhorn

Joined: Jul 08, 2005
Posts: 10
JFreeChart is a popular Java library drawing charts. In my application, I wish to render around 10 charts and I'd like to render them in parallel. JFreeChart renders its charts using BufferedImages. The code for paintComponent is here:



I already tried to thread this function via this code:



But this doesn't work. It only paints a gray screen which resizes correctly, but no buffered image. What's the best way to multithread the above paintComponent? (Note, I started this topic here:

http://ubuntuforums.org/showthread.php?p=9657545#post9657545 and I'm not a fan of crossposting. I just realized that this topic is a bit more advanced than most swing questions and thought the community here would be better able to answer my question.
pete stein
Bartender

Joined: Feb 23, 2007
Posts: 1561
I've never seen a background thread called from within the paintComponent method before, and while I suppose that there may be rare times when this may be done (but I haven't a clue as to one) I don't feel that this is one of them. Why not create the BufferedImage in a background thread not called by paintComponent, and then when done, call repaint() on the drawing JPanel, and in the paintComponent method if the BufferedImage isn't null, paint it by calling g.drawImage(myBufferedImage,.....)?

Oh, by the way, thanks for the link to the cross-post; it's much appreciated.
Austin Henggi
Greenhorn

Joined: Jul 08, 2005
Posts: 10
pete stein wrote:I've never seen a background thread called from within the paintComponent method before, and while I suppose that there may be rare times when this may be done (but I haven't a clue as to one) I don't feel that this is one of them. Why not create the BufferedImage in a background thread not called by paintComponent, and then when done, call repaint() on the drawing JPanel, and in the paintComponent method if the BufferedImage isn't null, paint it by calling g.drawImage(myBufferedImage,.....)?

Oh, by the way, thanks for the link to the cross-post; it's much appreciated.


From the code posted above, JFreeChart does render the chart to a BufferedImage first and then paints the buffered image to the canvas / JPanel. I think they do this because it allows for better abstraction among the renders, but if only one chart is rendered, it would slow things down a bit compared to directly rendering to the screen. One question I have though is how would multiple repaint events be handled? For example, when I resize a window, the Swing Event Dispatcher is actually firing off several repaint events, I'm guessing one per every pixel of frame size change. And if I did this with background thread, how I avoid spawning off one new event per pixel change? Maybe I'm not understanding or forgot some details about how swing works, but it seems that there needs to be some sort of filter for cutting out redundant repaint calls. Second, changes to the chart data set or other chart parameter (zooming, mouse cursor, etc) cause a call to paintComponent where a Graphics object is passed in. So if I were to also call repaint() when the rendering of the BufferedImage is finished, how would I tell whether the call to paintComponent means: 1) something changed, redraw the bufferedImage or 2) buffered image rendering done, paint bufferedImage? In case 1) once the BufferedImage is rendered, another call to paintComponent is made so we would enter an infinite loop. I don't have much experience with Swing Threading, but I think your idea is correct. I just don't see how to implement it.

Update: I was able to implement your approach because JFreeChart has a refreshbuffer flag which indicates whether the bufferedImage needs to be recomputed. So I simply made another function called refreshBuffer where I do just that if the buffer needs rendering. I do the rendering in a separate thread. There's a few problems. First although it draws the charts, there's some glitch at the beginning where all charts are the same for a second or two. Second, I still seem stuck using only one thread. CPU pegs at 25% (on a 4 core machine). I put in some getCurrentSystemTime and I see that each thread takes much longer to execute. So it seems like the threads are running in parallel, but only on one CPU core. I think some of these problems might relate to what I mentioned above in my previous post. If a chart receives multiple update calls, it will simply spawn a new thread for each call. Instead, what should happen is that if there's a more recent update call while the bufferedimage is being rendered, that rendering should stop (be interrupted) and start-over. This is because something has changed since the rendering started and therefore, rendering must be restarted. I suspect that Swing event handler has a way of dealing with this situation. In order to background render, I think there's something else that I'm still missing. Here's the code, all I really did was create a new function refreshBuffer which copies the bufferedImage rendering part of JFreeChart's original paintComponent method.


 
Don't get me started about those stupid light bulbs.
 
subject: How do I render and draw buffered Images in Parallel? - JFreeChart Question