repaint : Java Glossary

*0-9ABCDEFGHIJKLMNOPQRSTUVWXYZ (all)

repaint
repaint() requests an erase and redraw (update) after a small time delay. This allows time for more changes to the screen before actually redrawing. Without the delay you would end up repainting the screen many times a second, once for every tiny change. Imagine an odometer on screen spinning frantically. Repaint delay allows the odometer to spin without labouriously painting every single value. When you invoke repaint(), it sends a message to the native GUI (Graphic User Interface) suggesting that it would be a good idea if sometime in the distant future when it is convenient and things are slack and when the GUI feels in the mood that the painting work should be done. The native GUI enqueues this request, not the Java SystemEventQueue. As windows occlude each other and reveal each other, the native GUI itself decides that certain components, or parts of components also need to be repainted. The native GUI merges all these requests and removes the duplicates. It may reorder them so that background panels are repainted before the overlaying components.

You can give a hint that some repaints are more important than others by specifying a desired time in milliseconds by which you would like the repaint done. This is not a request for a delay. The technique is thus not suitable for animations. The GUI may decide to do the repaint right away, no matter what time you tell it.

The GUI then repaints some components on it own and indirectly generates ComponentEvent.COMPONENT_RESIZED, PaintEvent. UPDATE and PaintEvent.PAINT events to request the Java side of things handle the painting. These are enqueued into the SystemEventQueue just like ordinary events. These events in turn trigger the update() and paint() methods of the affected component to be called.

What triggers a repaint? There is a chain of occurrences:

  1. invalidate()

    (marking a container, and its enclosing containers, as needing to be re-laid out.) Sometimes application code directly calls invalidate(). More often invalidate() gets called as a side effect of adding or deleting a component, making a component visible or invisible (The AWT (Advanced Windowing Toolkit) is smart enough not to invalidate if you setVisible( true ) when the component is already visible), changing the size or location of a component with setSize(), setLocation() or setBounds(). invalidate() is also called as the first step in processing a COMPONENT_RESIZED event. Invoking invalidate by itself will not schedule a repaint or validate().
  2. validate()

    (similar to pack). This redoes the layout if necessary deciding on new sizes and locations of all the components in the container. Most often it gets called directly by application programmers, after a frame or other container been composed, but just before the Frame.setVisible( true ). validate() is also called as the second step in processing a COMPONENT_RESIZED event. Invoking validate() by itself will not schedule a repaint.
  3. setVisible( true ) (formerly known as show)

    setVisible( true ) for containers will typically invoke validate(). For now, it is probably safer not to count on setVisible doing this, and invoke it yourself. Unless the component is already visible, setVisible( true ) for components will invalidate() the parent container (and the enclosing containers too). Unless the container is already invisible, setVisible( false ) for containers will typically invalidate() the parent container (and the enclosing containers too). Unless the component is already invisible, setVisible( false ) for components will invalidate() the parent container (and the enclosing containers too). setVisible also schedules a repaint if necessary.
  4. repaint()

    does not actually paint. It calls the peer repaint which enqueues a request in some platform-dependent way inside the native GUI for a repaint. repaint()is also called as the third step in processing a COMPONENT_RESIZED event. Calling repaint() directly won’t invoke setVisible() or validate().
  5. SystemEventQueue

    When the native GUI is good and ready, it indirectly enqueues a PaintEvent.PAINT or PaintEvent.UPDATE event into Java’s SystemEventQueue using Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(Event e). The event dispatcher in EventDispatcherThread.run eventually pops events off the SystemEventQueue and dispatches them. The PAINT and UPDATE events are specially handled. For an update event, the component’s update() method is invoked, and passed a Graphics state which includes the clip region to be erased/redrawn.
  6. The

    update()

    method typically erases the component (the erasure is automatically clipped), or does nothing if the paint method will cover the entire area. Then it typically calls paint.
  7. The

    paint()

    method then actually does the drawing, using the Graphics state object passed to it which includes the clip region. The paint routine is usually oblivious of the clip region. It just paints everything, and allows the AWT to prune off the unwanted data. Container.update() and Container.paint() arrange to paint all the contained lightweight components after painting the background of the container. The native GUI handles scheduling or actually repainting of any contained heavyweight components. updateAll and paintAll are responsible for painting all the contained components.
You might expect Label.setText(), as a side effect, to call repaint(), but it does not. The native GUI is smart enough to internally handle the repainting as a side effect of peer.setText(). Anything that just changes the contents of the display, but not its size or location need not invalidate(), just a repaint() since the old layout will do fine.

Instead of using the repaint mechanism, you can use Component.getGraphics to handle your animation changes.

Faster Repaints

One simple technique to speed up repaint is to use
repaint( int x, int y, int width, int height );
When you know that only a portion of the component has changed. You can further speed things up, in your paint or paintComponent method by paying attention to the clip bounds. Anything you paint outside the clipping region will just be ignored. For efficiency, you should make some effort to avoid rendering large amounts of screen real estate outside it.
// Graphics g is passed to your paint as a parameter.
// get x, y, width and height of region we are actually painting
Rectangle r = g.getClipBounds();

Another technique is to render the image offscreen, and then when it is needed, blast it onscreen with a drawImage bit/blt. The rendered image might be huge. You just blast a piece of it onto the screen each time. You can then scroll either horizontally or vertically very quickly by just copying a piece of the huge image to the screen. You might construct your huge image in tiles, and just create them and discard them as needed. They will fit together seamlessly when you blast them on screen. You can get clever and have a background thread preemptively create nearby offscreen tiles that might be soon needed. Consider using soft references to keep as many tiles around as will fit. The problem is, when you have a large Image, the amount of memory needed for the bit map goes up as the square of the size. You don’t necessarily have room for the entire Image you pan over.

For super speed, you store some of your offscreen images in the video REGEN (Regenerate) buffer using VolatileImage. I used this technique for the Las Vegas Hilton Hotel’s giant screens that slowly scroll images. The size of the REGEN buffer is limited, so you just keep in there what you plan to view in the near future. For continuous displays, you can use a squirrel cage backing image that wraps around. You continuously update the backing image, never creating a new object. To scroll, you copy two chunks from the backing image to the screen. VolatileImage is tricky because at any point your backing store can disappear on you.

Repaints and ScrollPanes

If you do a repaint of an Applet containing a ScrollPane containing a Canvas, from the Applet’s point of view, only the visible part of the Canvas needs to be re-rendered. If your intent was to invalidate the entire Canvas, including the currently invisible parts, and re-render with different data, you will have to also do a Canvas. repaint to logically invalidate the entire invisible Canvas. Otherwise, when you scroll, old pre-rendered stuff from before the repaint will reappear. because the AWT caches your paint renderings when it can.

Tips

Learning More

Oracle’s Javadoc on repaint package : available:
Oracle’s Javadoc on paint package : available:

This page is posted
on the web at:

http://mindprod.com/jgloss/repaint.html

Optional Replicator mirror
of mindprod.com
on local hard disk J:

J:\mindprod\jgloss\repaint.html
logo
Please the feedback from other visitors, or your own feedback about the site.
Contact Roedy. Please feel free to link to this page without explicit permission.
no blog for this page
IP:[65.110.21.43]
Your face IP:[174.129.103.100]
You are visitor number