• Post Reply Bookmark Topic Watch Topic
  • New Topic

Struggling to understand paint() vs repaint()  RSS feed

 
Alan Smith
Ranch Hand
Posts: 185
Firefox Browser Linux Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi all,

Can someone please explain the above to me like I am a three year old? I have some example code below that draws a ball moving across the screen. Calling super.paint(g) clears the screen correctly before the ball gets repainted, super.repaint does not. So what is the difference between the two? Are they just poorly named methods?



I'm just trying to get into simple 2D game programming with Swing. Struggling with the basics already

Edit: to add to this, the javadoc for JPanels paint method states:
"Applications should not invoke <code>paint</code> directly, but should instead use the <code>repaint</code> method to schedule the component for redrawing."

Repaint does not work to correctly redraw the panel and the ball as seen in my example above, so I had to call super.paint.

Thanks
 
Darryl Burke
Bartender
Posts: 5167
11
Java Netbeans IDE Opera
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First off, never call repaint() from within a painting method.

Read the API for repaint() (inherited from Component)
If this component is a lightweight component, this method causes a call to this component's paint method as soon as possible.
For more insight on the painting mechanism, follow the link in that API and also review JComponent#paint
This method actually delegates the work of painting to three protected methods: paintComponent, paintBorder, and paintChildren.
 
Gary W. Lucas
Ranch Hand
Posts: 65
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

If you haven't already done so, it may help to look at The Java Tutorials: Performing Custom Painting at https://docs.oracle.com/javase/tutorial/uiswing/painting/index.html

In particular, the section titled "A Closer Look at the Paint Mechanism".

Basically, repaint() does not perform any actual painting, but instead schedules an event on a "repaint queue" meaning that Java will invoke the class's paint() method at its next opportunity. Java implements a strategy for scheduling repaints that tries to make rendering as efficient as possible. To do so, it sometimes compresses actions, treating multiple calls to overlapping calls to repaint() as a single action. So repaint() is what you call when you want to trigger a paint operation. Your main method does that just fine. I would discourage you from overriding or otherwise modifying the repaint() methods, especially if you want to produce maintainable code.

Also, at least at the beginning of your exploration, the method of JPanel that you want to override is paintComponent(), which is called by paint(), not paint() itself. That section on "A Closer Look" gives some more details on this issue.

Gary



 
Gary W. Lucas
Ranch Hand
Posts: 65
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, I added a bit of instrumentation to your main loop as shown below. On my Windows box, the application attained an update rate of one moveBall operation every 15 milliseconds, or 5 milliseconds longer than your call to Thread.sleep(10). That's not a big deal since you were just writing a test program, but I wanted to point out that it wasn't the rendering speed that was the issue. Java can draw thousands of graphics primitives in 10 milliseconds. As you move forward on your game, you'll want to investigate other kinds of scheduling and animation approaches than a simple delay loop.

 
Darryl Burke
Bartender
Posts: 5167
11
Java Netbeans IDE Opera
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Gary, it's wrong to call sleep(...) on the EDT, or to call repaint() on any other Thread.
 
Gary W. Lucas
Ranch Hand
Posts: 65
6
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alan,

Darryl Burke makes a good point about the Event Dispatch Thread (EDT). You are calling both Thread.sleep() and repaint() from the main thread. Putting sleep in the main thread (rather than the EDT) shouldn't hurt anything, but if you want to introduce timing factors into your user-interface code, you should consider java.Swing.Timer (not to be confused with the other classes that are, unfortunately, also named Timer). Any modifications to objects related to the user-interface (such as your frame) should be made in the EDT, not in some other thread. The SwingUtilites class has two methods -- invokeAndWait() and invokeLater() to support accessing the user-interface from non-EDT threads.
 
Campbell Ritchie
Sheriff
Posts: 53779
128
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Gary W. Lucas wrote: . . . Putting sleep in the main thread (rather than the EDT) shouldn't hurt anything . . .
…but it will have no effect because the painting is done on the EDT.

You are right to suggest using a Timer.
 
Rob Camick
Ranch Hand
Posts: 2756
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For a more in depth technical explanation of painting check out: Painting in AWT and Swing

 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!