• 沒有找到結果。

Invalidating and Repainting

在文檔中 Java™ Swing, 2nd Edition (頁 93-96)

James Elliott

Device 0: X11GraphicsDevice[screen=0]

3.5 The JComponent Class

3.5.5 Invalidating and Repainting

Swing uses a repaint manager to repaint lightweight components. The repaint manager maintains a queue of rectangular areas that need to be repainted; it calls these areas " dirty regions." Sometimes the rectangles are the size of entire components; at other times they are smaller. The repaint manager processes repaint requests as they are added to the queue, updating dirty regions as quickly as possible while preserving the visual order of the components. In AWT, the

Component

class contains an overloaded

repaint( )

method that allows you to repaint only a subrectangle of the component. The same is true with

JComponent

. If only part of a component needs to be repainted, the repaint manager invokes an overloaded version of the

repaint( )

method that takes a

Rectangle

parameter.

JComponent

contains two

repaint( )

methods that add specified rectangles directly to the dirty region. Like AWT, you should call these methods instead of invoking the

paint( )

method directly, which bypasses the

RepaintManager

. The

RepaintManager

class is discussed in more detail in Chapter 28.

3.5.5.1 The paint( ) method and opaqueness

Because

JComponent

is the direct subclass of the AWT

Container

class, it is the official recipient of repaint requests through its

paint( )

method. As you might guess,

JComponent

must delegate this request by passing it to the

paint( )

method of the UI-delegate object. The responsibility, however, does not end there.

JComponent

is actually responsible for painting three items: the component itself, any borders associated with the component, and any children that it contains.

The order is intentional. Components drawn last are always on top; hence, child components always paint over their parents.

JComponent

contains three protected methods that it uses to complete this functionality:

protected void paintComponent(Graphics g)

protected void paintBorder(Graphics g) protected void paintChildren(Graphics g)

Because of the complexity involved in painting and repainting Swing components, you should always try to override these three methods while creating your own components. Also, do not try to override

paint( )

unless you call

super.paint( )

.

SDK 1.4 introduced a series of methods relating to printing rather than painting. Calling the

print( )

or

printAll( )

methods (both public and available since 1.2) now results in calls to

printComponent( )

,

printBorder( )

, and

printChildren( )

in that order.

When painting or printing

JComponent

subclasses, the

Graphics

object passed to these methods is actually a

Graphics2D

object. You can cast it as such if you want to take advantage of the increased functionality available in the 2D packages. Check out Jonathan Knudsen's Java 2D Graphics (O'Reilly) for more detailed information.

The boolean property

opaque

dictates the transparency of each Swing object.[1]

If this property is set to

false

, the component's background color is transparent. This means that any areas left untouched by the component's rendering allow graphics in the background to show through. If the property is set to

true

, the rectangular painting region is completely filled with the component's background color before it is rendered. Incidentally, transparency was not possible before lightweight components. Native peer objects in Java 1.0 always drew their component on a solid rectangle; anything that was behind the component was erased. Figure 3-5 shows the difference between an opaque and a transparent (nonopaque) label, both with a dark background color. The label on the left is transparent, so its background color is ignored; the label's text appears on top of the container's relatively light background.

[1] In JDK 1.2, the

isOpaque( )

method is defined in

java.awt.Component

.

Figure 3-5. Transparency and opaqueness

JComponent

can optimize its repainting time if none of its children overlap; this is because the repaint manager does not have to compute the hidden and visible areas for each child component before rendering them. Some containers, such as

JSplitPane

, are designed so that overlap between child components is impossible, so this optimization works nicely. Other containers, such as

JLayeredPane

, have support for child components that can overlap.

JComponent

contains a property that Swing frequently calls upon to see if it can optimize component drawing:

optimizedDrawingEnabled

. In

JComponent

, this property is set to

true

by default. If overlap occurs in a subclass of

JComponent

, the subclass should override the

isOptimizedDrawingEnabled( )

accessor and return

false

. This prevents the repaint manager from using the optimized drawing process when rendering the container's children.

JComponent

contains a boolean read-only property (

paintingTile

) that indicates whether the component is currently in the process of painting a tile , which is a child component that does not overlap any other children. The

isPaintingTile( )

method returns

true

until all tiles have been painted.

The

visibleRect

property is a

Rectangle

that indicates the intersection of the component's visible rectangles with the visible rectangles of all of its ancestors. Why the intersection? Remember that you can have a contained object that is clipped by its parent. For example, you can move an internal frame so that a portion of it falls outside the parent window's clipping region. Therefore, the visible portion (the portion that is actually drawn to the screen) consists only of the intersection of the parent's visible portion and the child's visible portion. You typically do not need to access this property.

The

validateRoot

property is

false

by default. If it is set to

true

, it designates this component as the root component in a validation tree. Recall that each time a component in a container is invalidated, its container is invalidated as well, along with all of its children. This causes an invalidation to move all the way up the component hierarchy, stopping only when it reaches a component for which

isValidateRoot( )

returns

true

. Currently, the only components that set this property to

true

are

JRootPane

(which is used by all the Swing top-level components),

JScrollPane

, and

JTextField

.

The

topLevelAncestor

property contains a reference to the top-level window that contains this component, usually a

JWindow

or

JApplet

. The

rootPane

property contains the low-level

JRootPane

for this component;

JRootPane

is covered in more detail in Chapter 8.

Finally,

JComponent

contains a property called

autoscrolls

, which indicates whether a component is capable of supporting autoscrolling. This property is

false

by default. If the property is

true

, an

Autoscroller

object has been set over this component. The

Autoscroller

object monitors mouse events on the target component. If the mouse is dragged outside the component, the autoscroller forces the target component to scroll itself. Autoscrolling is typically used in containers such as

JViewport

.

在文檔中 Java™ Swing, 2nd Edition (頁 93-96)

相關文件