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 oddometer on screen spinning frantically. Repaint delay allows
the oddometer to spin without labouriously painting every single value.
When you invoke repaint(), it sends
a message to the native GUI 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.
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 occurences:
-
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 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().
-
validate() (formerly knows
as 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.
- 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 visibele, 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.
-
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().
-
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.
-
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.
-
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. See also event, invalidate, validate, setVisible, update,
paint.