Friday, November 13, 2009

28.3 Lightweight Versus HeavyweightComponents




I l@ve RuBoard










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.




Figure 28-6. Consider heavyweight components as easels and lightweight components as drawings



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

Layout manager



Can be used to mix heavyweight and lightweight?



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.




Figure 28-7. Lightweight menus obscured by heavyweight panels






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

lightWeightPopupEnabled



Drawn inside the top-level container



Drawn outside the top-level container



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.




Figure 28-8. 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.




Figure 28-9. Using heavyweight components inside of an internal frame












    I l@ve RuBoard



    No comments: