• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

paintComponent() troubles

 
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.



 
Rancher
Posts: 3324
32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Rancher
Posts: 43081
77
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You can pass a reference to the Graphics object to the thread/timer Rob mentioned.
 
Georgios Fofikos
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Rancher
Posts: 43081
77
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Rancher
Posts: 3324
32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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.
 
Evil is afoot. But this tiny ad is just an ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic