A layered pane is a Swing container that provides a third dimension for positioning components: depth, also known as Z order. When adding a component to a layered pane, you specify its depth as an integer. The higher the number, closer the component is to the "top" position within the container. If components overlap, the "closer" components are drawn on top of components at a lower depth. The relationship between components at the same depth is determined by their positions within the depth.
Every Swing container that has a
root pane —
such as
JFrame
,
JApplet
,
JDialog
, or
JInternalFrame
—
automatically has a layered pane.
Most programs do not explicitly
use the root pane's layered pane,
so this section will not discuss it.
You can find information about it in
The Root Pane,
which provides an overview, and
The Layered Pane,
which has further details. This section tells you how to create your own layered pane
and use it anywhere you can use a regular Swing container.
Swing provides two layered pane classes.
The first,
JLayeredPane
, is the class that root panes use
and is the class used by the
example in this section.
The second,
JDesktopPane
,
is a JLayeredPane
subclass
that is specialized for the task of holding internal frames.
For examples of using JDesktopPane
,
see How to Use Internal Frames.
Here is a picture of an application that creates a layered pane and places overlapping, colored labels at different depths:
LayeredPaneDemo.java
that creates the layered pane:
layeredPane = new JLayeredPane(); layeredPane.setPreferredSize(new Dimension(300, 310)); layeredPane.setBorder(BorderFactory.createTitledBorder( "Move the Mouse to Move Duke")); layeredPane.addMouseMotionListener(new MouseMotionAdapter() { ... });
JLayeredPane
's only constructor — the
no-argument constructor — to create the layered pane.
The rest of the code
uses methods inherited from superclasses
to give the layered pane a preferred size and a border,
and add a mouse-motion listener to it.
The mouse-motion listener
just moves the Duke image around in response to mouse movement.
Although we do not show the code here,
the example adds the layered pane to the frame's content pane.
As we will show you a bit later,
you add components to a layered pane using
an add
method.
When adding a component to a layered pane,
you specify the component depth,
and optionally, its position within its depth.
The layered pane in the demo program contains
six labels — the five colored labels
and a sixth one that displays the Duke image.
As the program demonstrates,
both the depth of a component
and its position within that depth
can change dynamically.
The rest of this section covers these topics:
for (int i = 0; i < ...number of labels...; i++) { JLabel label = createColoredLabel(...); layeredPane.add(label, new Integer(i)); ... }
createColoredLabel
method
in the source code for the program.
It just creates an opaque JLabel
initialized with a background color,
a border, some text, and a size.
The example program uses a two-argument version
of the add
method.
The first argument is the component to add,
the second is an Integer
object,
specifying the depth.
This program uses the for
loop
iteration variable to specify depths.
The actual values do not matter much.
What matters is the relative value of the depths
and that you are consistent within your program
in how you use each depth.
LayeredPaneDemo
to use
the root pane's layered pane.
With the modifications,
you can see how the dragging Duke image
relates to the combo box in the control panel.
As you can see from the example program,
if components overlap,
components at a higher depth
are on top of components at a lower depth.
To change a component depth dynamically,
use the setLayer
method.
In the example,
the user can change Duke's layer
by making a selection from the combo box.
Here is the actionPerformed
method
of the action listener registered on the combo box:
public void actionPerformed(ActionEvent e) { int position = onTop.isSelected() ? 0 : 1; layeredPane.setLayer(dukeLabel, layerList.getSelectedIndex(), position); }
setLayer
method used here
takes three arguments:
the component whose depth is to be set,
the new depth, and the position within the depth.
JLayeredPane
has a two-argument version
of setLayer
that takes only the component and the new depth.
That method puts the component at the bottom position in its depth.
Integer
.
When using setLayer
to change a component's
layer, you use an int
.
You might think that
if you use an int
instead of an Integer
with the add
method, the compiler would complain
or your program would throw an illegal argument exception.
But the compiler says nothing, which results in a
common layered pane problem.
You can use the API tables at the end of this section
to check the types of the arguments and return values
for methods that deal with layers.
final ImageIcon icon = createImageIcon("images/dukeWaveRed.gif"); ... dukeLabel = new JLabel(icon); ... dukeLabel.setBounds(15, 225, icon.getIconWidth(), icon.getIconHeight()); ... layeredPane.add(dukeLabel, new Integer(2), 0);
add
method.
The third argument specifies the Duke label
position within its depth,
which determines the component's relationship with
other components at the same depth.
Positions are specified with an int
between -1 and (n - 1),
where n is the number of components at the depth.
Unlike layer numbers,
the smaller the position number,
the higher the component within its depth.
Using -1 is the same as using n - 1;
it indicates the bottom-most position.
Using 0 specifies that the component should be
in the top-most position within its depth.
As the following figure shows,
with the exception of -1,
a lower position number indicates a higher position within a depth.
actionPerformed
method
for the action listener registered on the check box:
public void actionPerformed(ActionEvent e) { if (onTop.isSelected()) layeredPane.moveToFront(dukeLabel); else layeredPane.moveToBack(dukeLabel); }
moveToFront
method moves Duke to the front (position 0).
And when the user deselects check box,
Duke gets moved to the back with the moveToBack
method.
You can also use the setPosition
method or
the three-argument version of setLayer
to change a component's position.
The example uses the setBounds
method
to set the size and position of each of the labels:
dukeLabel.setBounds(15, 225, icon.getIconWidth(), icon.getIconHeight()); ... label.setBounds(origin.x, origin.y, 140, 140);
setPosition
to change Duke's position:
dukeLabel.setLocation(e.getX()-XFUDGE, e.getY()-YFUDGE);
GridLayout
,
using that layout manager to lay out six colored labels.
LayeredPaneDemo2.java
.
You can run LayeredPaneDemo2 (
download JDK 6). If you want to compile the example,
consult the
example index
for a list of all necessary files.
Many programs use intermediate containers (such as panels) and their layout managers to lay out components on the same layer, but use absolute positioning to lay out components on different layers. For more information about absolute positioning, see Doing Without a Layout Manager (Absolute Positioning).
JLayeredPane
constructors and methods.
Other methods you are most likely to invoke on
a JLayeredPane
object are those
it inherits from its superclasses,
such as setBorder
, setPreferredSize
, and so on.
See
The JComponent API
for tables of commonly used inherited methods.
The API for using layered pane falls into these categories:
Method or Constructor | Purpose |
---|---|
JLayeredPane() | Create a layered pane. |
JLayeredPane getLayeredPane() (in JApplet , JDialog ,
JFrame , and
JInternalFrame )
|
Get the automatic layered pane in an applet, dialog, frame, or internal frame. |
Method | Purpose |
---|---|
void add(Component) void add(Component, Object) void add(Component, Object, int) |
Add the specified component to the layered pane.
The second argument, when present, is an Integer
that indicates the layer.
The third argument, when present,
indicates the component's position within its layer.
If you use the one-argument version of this method,
the component is added to layer 0.
If you use the one- or two-argument version of this method,
the component is placed underneath
all other components currently in the same layer.
|
void setLayer(Component, int) void setLayer(Component, int, int) |
Change the component's layer. The second argument indicates the layer. The third argument, when present, indicates the component's position within its layer. |
int getLayer(Component) int getLayer(JComponent) |
Get the layer for the specified component. |
int getComponentCountInLayer(int) | Get the number of components in the specified layer. The value returned by this method can be useful for computing position values. |
Component[] getComponentsInLayer(int) | Get an array of all the components in the specified layer. |
int highestLayer() int lowestLayer() |
Compute the highest or lowest layer currently in use. |
Method | Purpose |
---|---|
void setPosition(Component, int) int getPosition(Component) |
Set or get the position for the specified component within its layer. |
void moveToFront(Component) void moveToBack(Component) |
Move the specified component to the front or back of its layer. |
JLayeredPane
and where those examples are described.
Example | Where Described | Notes |
---|---|---|
LayeredPaneDemo
|
This section | Illustrates layers and intra-layer positions
of a JLayeredPane .
|
LayeredPaneDemo2
|
This section | Uses a layout manager to help lay out the components in a layered pane. |
RootLayeredPaneDemo
|
The Layered Pane | A version of
LayeredPaneDemo
modified to use the root pane's layered pane.
|
InternalFrameDemo
|
How to Use Internal Frames | Uses a JDesktopFrame to manage internal frames.
|