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

paintComponent() troubles

Georgios Fofikos
Greenhorn

Joined: Dec 28, 2009
Posts: 5
Hi forum and my warm wishes for a productive (and healthy) new year for you and your family!


I have one object that extends JPanel, overrides paintComponent() and initializes/starts other objects, each of them running a thread that is responsible for some stuff, including painting itself on the panel.
One design that I tried but it seems a bit botched is the main object's Graphics2D reference being shared amongst everyone so that each object can use it to draw itself (but having multiple threads changing the Graphics2D reference attributes will be a problem).
My main glitch is that I cannot animate anything in the panel.
For example in TestPaintClass1:



Instead of having the drawString method draw the new number each second and having it displayed, I get nothing (because paintComponent() waits untill the loop finishes, that is in 1000 seconds so that it can display the final result). I tried repaint() but it didn't work. Searching in the corresponding APIs did not yeild much results either.

This is an just an example, but inside the paintComponent() there should be a call to a display method of a TestPaintClass2 object to paint/update itself.
So to conclude: one main object that inits a JPanel/JFrame and has a Graphics2D reference and a sort collection of other objects that are running a thread which among other things is responsible to paint itself in the main JPanel/JFrame constructed from the main object.
The botched design does not concern me for now. The problem is in the updating of the painting of each object.

Thanks for your time,
george.



Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2215
    
    7
I have one object that extends JPanel, overrides paintComponent() and initializes/starts other objects, each of them running a thread that is responsible for some stuff, including painting itself on the panel.


Well, you should not be starting Threads or "sleeping" or anything like that. The paintComponent() method is strictly for painting and there should not be any animation code in the method.

If you want to do animation then you start a Swing Timer. When the Timer fires you "update the location" of your components.
If you are using Swing components then thats all you need to do the component will repaint themselves automatically. If you are painting your components then you need to invoke repaint() on the panel to tell it to do the drawing of the components in the new location or state.
Georgios Fofikos
Greenhorn

Joined: Dec 28, 2009
Posts: 5
Thanks Rob!

But my problem is that when paintComponent() ends, and the execution gets back to main, I no longer "can paint" using the 'Graphics g' object, because the reference is destroyed.
I can only seem to be able to reference it only in the context of paintComponent(). Is there another way for this ?

Regards,

george.
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42608
    
  65
You can pass a reference to the Graphics object to the thread/timer Rob mentioned.


Ping & DNS - my free Android networking tools app
Georgios Fofikos
Greenhorn

Joined: Dec 28, 2009
Posts: 5
Hello!

But I can only pass the reference only within the paintComponent() method because when the method ends, the reference is destroyed, so how is this different from what I do? Rob mentioned that animation code should not be put inside paintComponent().
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 42608
    
  65
At the end of the method, the "g" reference goes out of scope, but the object doesn't disappear. So if you pass another reference to the object to some other method you can still use it.

And yes, nothing lengthy should be done in the paintComponent method - it should return quickly.
Georgios Fofikos
Greenhorn

Joined: Dec 28, 2009
Posts: 5
Ok, but I`m not 100% certain that I understood how the Swing Timer will work. I'll read up and try some code and I'll get back to you! :-)

Thanks for the tip.

Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2215
    
    7
I can only seem to be able to reference it only in the context of paintComponent().


Exactly. and that is the way it should be.

You should NOT be doing painting outside of the paintComponent() method. You should NOT be passing the Graphics object around.

All the paintComponent() method should do is paint the "state" of your component. If you change the "state" then you need to invoke repaint() so the component can repaint itself.

Take a look at Custom Painting Approaches and take up the animation challenge. Concentrate on the "DrawOnComponent" example as it will be the easiest to animate.

To add animation you create a Timer. When the Timer fires you will simply need to loop through the List containing all the ColoredRectangles. Try incrementing the (x,y) position of each rectangle. Then you just invoke reapaint() on the panel and the paintComponent() method will iterate throught the List and paint the rectangles in the new location. So you don't need access to the Graphics, but you do need access to the List containing the rectangle to be painted.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: paintComponent() troubles