28.3 Lightweight Versus HeavyweightComponents
The issue of lightweight versus heavyweight components has complicated Swing since its inception. The concept of lightweight components managed entirely by Java code is, of course, one of the major benefits introduced by Swing. What has confused the majority of programmers from the start is the issue of z-order, or layering, between Swing lightweight components and AWT heavyweight components.
28.3.1 Understanding the Z-Order
In Swing, it might help to think of a heavyweight component as an artist's easel. Top-level components in Swing (JWindow, JDialog, JApplet, and JFrame) are heavyweight, while everything else isn't. Lightweight components added to those top-level heavyweights can be thought of as drawings on the canvas of each easel. Therefore, if another heavyweight component (another easel) is moved in front of the original easel, or even attached to it, the lightweight paintings on the original easel are obscured. Figure 28-6 demonstrates this analogy.
The same is true for how Swing interprets the z-order of lightweight and heavyweight components, even in a container. If a heavyweight component is added to a container that has lightweight components, the heavyweight is always on top; the lightweight components must share the same z-order as the parent container. In addition, lightweight components cannot draw themselves outside the container (easel) they reside in, or they are clipped.
28.3.2 Mixing Swing and AWT
Our first bit of advice is: don't do it. If you can get around mixing the two (by solely using lightweight components), then you'll save yourself a mountain of testing grief. That being said, let's discuss some of the common problems that you're likely to run into if you decide, or are forced, to make the attempt.
28.3.2.1 Overlapping heavyweight and lightweight components
As we mentioned above, the heavyweight component always displays itself on top despite the intended z-order. The basic strategy is to ensure that lightweight components and heavyweight components in the same container do not overlap. On that note, Table 28-2 shows a list of
layout managers and panes that can and cannot be used to mix lightweight and heavyweight components.
Table 28-2. Heavyweight-friendly Swing layout managers and panes
|
BorderLayout
|
Yes
|
BoxLayout
|
Yes
|
CardLayout
|
Yes
|
FlowLayout
|
Yes
|
GridBagLayout
|
Yes
|
GridLayout
|
Yes
|
JLayeredPane
|
No
|
JScrollPane
|
No
|
JSplitPane
|
Yes
|
JTabbedPane
|
Yes*
|
OverlayLayout
|
No
|
SpringLayout
|
No
|
*In some cases, this layout manager may still fail.
|
|
28.3.2.2 Heavyweight components in front of lightweight menus
Heavyweight components are always drawn in front of lightweight menus. This creates another (somewhat comical) Swing and AWT problem. While the menu bar is usually not disturbed, any menus that are drawn are placed behind the component. Hence, a user may bring up a menu but be unable to select a specific menu item.
Figure 28-7 shows four heavyweight panels positioned in front of a lightweight Edit menu. While you can still select a menu, you can't see it � the repainting mechanism in Java redraws the heavyweight panels over the menus as they are activated. Because anchored menus are essentially combinations of buttons and pop-up menus, you will have the same problem if you attach a lightweight pop-up menu to a heavyweight component.
28.3.2.3 Pop ups
Pop-up components are easy targets for these problems. Pop-up components include elements found in Swing menus, pop-up menus, and combo boxes. These components get into trouble because they may be called upon to display themselves outside the confines of their heavyweight top-level container. For example, if you activate a pop-up menu in a component near the bottom of a JFrame, the pop up might extend beyond the bottom of the frame when it is raised. If this is the case, then it cannot be rendered using a lightweight component; if it is, it is clipped against the container boundary.
Swing knows that if this is the case, it can use a heavyweight AWT Window to display the pop up instead. However, what if you need to include a heavyweight component inside a container in whi'ch pop ups are used? Fortunately, pop-up components in Swing contain a property that allows them to switch from lightweight to heavyweight to display themselves. Incidentally, this is a type of behavior that you may wish to mimic if you create your own pop-up components.
This single boolean property is called lightWeightPopupEnabled. It can be set to true or false, depending on how you want Swing to display the component. If lightWeightPopupEnabled is true, the component uses a lightweight component to display itself if it is wholly contained inside a top-level component, and uses a Panel otherwise. If lightWeightPopupEnabled is false, the component uses either a heavyweight AWT Panel or a Window to display itself, depending on where it is displayed. Table 28-3 shows which type of component Swing uses in various scenarios.
Table 28-3. The lightWeightPopupEnabled property
|
true
|
Lightweight Popup
|
Heavyweight Window
|
false
|
Heavyweight Panel
|
Heavyweight Window
|
For example, you can get around the lightweight menu problem discussed earlier by setting the lightWeightPopupEnabled property to false on each of the pop-up portions of the menus:
JMenu menu = new JMenu("Edit"); menu.getPopupMenu( ).setLightWeightPopupEnabled(false);
Although there will be a noticeable flicker as the components struggle to repaint themselves, the menu should end up on the right side of the heavyweight component included in the container. If you plan to mix lightweight and heavyweight components, you should always set the lightWeightPopupEnabled property for any pop ups in the application to false, including menus.
28.3.2.4 Heavyweight components in JScrollPane
There really isn't a workaround to make heavyweight components work correctly in a
JScrollPane. What invariably happens is that the component inside the JScrollPane object fails to clip properly when it is placed inside the pane, and visible artifacts are easy to pick up. Stay as far away from this as you possibly can. Figure 28-8 shows the problem of placing heavyweight components in a JScrollPane object.
28.3.2.5 Heavyweight components inside internal frames
Placing heavyweight components inside internal frames is also an inherently bad idea. The problem here is that internal frames can, by design, overlap. If an overlap occurs, and the internal frame with the heavyweight component is on the bottom, the component is still drawn on top of the overlapping internal frame. Figure 28-9 shows what happens when a heavyweight component in one internal frame overlaps another internal frame. Again, stay away from this scenario.
|
No comments:
Post a Comment