aspose file tools*
The moose likes Swing / AWT / SWT and the fly likes start/stop drawing Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "start/stop drawing" Watch "start/stop drawing" New topic
Author

start/stop drawing

Phil Freihofner
Ranch Hand

Joined: Sep 01, 2010
Posts: 115
    
    1
Hi -

Am curious about something. Suppose I wish to first draw a background, then gradually draw more objects on a JPanel, one by one. Does this all have to be done via a single paintComponent() call? In otherwords, write the code that does the entire draw in one pass in paintComponent()? In that case, I'm thinking I'll have to try putting in checks to a "pause" boolean along the way to manage the starts and stops, treating paintComponent as a separate thread, if that is allowed.

Or is there a way to create some sort of Graphic object and draw my objects in it gradually over time, then have the paintComponent() display that object in its various states of completion, e.g., when I call repaint(), paintComponent() draws this Graphic object. What sort of Graphic object would that be?

Or is there a way to call paintComponent() and have the draws that are called accumulate instead of being overwritten? This seems hard to do if one wants to make the first call one that clears the board and creates a background, but doesn't want the additional calls to redo this.

Thanks!
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19696
    
  20

Phil Freihofner wrote:Am curious about something. Suppose I wish to first draw a background, then gradually draw more objects on a JPanel, one by one. Does this all have to be done via a single paintComponent() call? In otherwords, write the code that does the entire draw in one pass in paintComponent()?

Yes.

In that case, I'm thinking I'll have to try putting in checks to a "pause" boolean along the way to manage the starts and stops, treating paintComponent as a separate thread, if that is allowed.

It isn't. All GUI interaction, from keyboard presses and mouse clicks to painting of the GUI, need to be done on the Event Dispatcher Thread.

Or is there a way to create some sort of Graphic object and draw my objects in it gradually over time, then have the paintComponent() display that object in its various states of completion, e.g., when I call repaint(), paintComponent() draws this Graphic object. What sort of Graphic object would that be?

Or is there a way to call paintComponent() and have the draws that are called accumulate instead of being overwritten? This seems hard to do if one wants to make the first call one that clears the board and creates a background, but doesn't want the additional calls to redo this.

You could try using a BufferedImage. This has a method called createGraphics() which will return a Graphics2D object. You can draw onto this, then dispose() it. Then all you need to do is draw the one image in your paintComponent method.

This requires some extra attention if you also allow currently drawn contents to be removed or modified, but it could be as simple as creating a new BufferedImage and refilling it only when you need to.


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Phil Freihofner
Ranch Hand

Joined: Sep 01, 2010
Posts: 115
    
    1
Thanks! I am able to draw on a BufferedImage and then call repaint() and display the BufferedImage. However, I'm still having troubles. I can't seem to get the individual repaint() commands to print. Only a final repaint() version appears.

Here is the code:

for (int i=0; i<10; i++){
gBuf.draw(makeLine());
try {
Thread.sleep(500);
}
catch(InterruptedException e) {
return;
}
repaint();
}

This code is calling the following:

public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(buf,0,0,null);
}

where "buf" is the BufferedImage used to create "gBuf".


Instead of 10 snapshots at the rate of 2 per second, the entire image appears at the 5 second point.

I tried using: this.paintImmediately(rectArea) in place of the repaint() above, but I get the same result--no action on the screen until the for loop has finished executing.

Maybe I got lucky with some other animation code I wrote. In that instance, there's a Timer that sends out updateMovement() commands to various registered "animatable" objects and repaint() commands to the component where they are being displayed, as fast as every 20msec, and the animation works fine. Maybe try that approach here, too? Seems like this much extra programming shouldn't be needed though, if I just want to force a repaint of a screen area after a short snooze.

Suggestions much apprectiated! Thanks.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19696
    
  20

Concurrency in Swing

Oh, and please UseCodeTags next time.
Phil Freihofner
Ranch Hand

Joined: Sep 01, 2010
Posts: 115
    
    1
Thanks for the tip on how to format code examples!

The cited tutorial is good background info. I also wrangled with the following article which acknowledges the situation ("overlapping" events being collapsed on the event dispatch thread), which I post for anyone following. I admit I was wishing for more example code to clear up many ambiguities I found in the writing.

"Painting in AWT and Swing: Good Painting Code is the Key to App Performance" http://java.sun.com/products/jfc/tsc/articles/painting/index.html

Interestingly, this article suggests that paintImmediately() CAN be used as an entry point for synchronous paint requests. I haven't tried it yet though. There are some warnings and a link for further reading:

"Threads and Swing"
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
Looks very interesting!


On the reprint() commands being collapsed: I find it curious that this occurred with an interpolation of 500 msecs (as in my obsolete code clip):



Repaint commands probably don't actually sit on the event-dispatch thread 500 msecs, correct? So, I'm thinking there is some other mechanism for determining "overlap" in this case.

In contrast, I now create a Timer external to the panel to both periodically update the BufferedImage and call the panel's reprint() via method calls to the panel, and this seems to speed up the "frame rate" to a granularity of at least 40 or 30 msecs, maybe even a bit faster, though it gets hard to tell by eyeball at the quicker speeds. This solution is covering most of the requirements of my friend who requested the applet. (temporary link during dev of this applet, for the curious: adonax.com/Jean/HowWide.html)
 
Consider Paul's rocket mass heater.
 
subject: start/stop drawing