Using Swing Components |
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. Components at a higher depth overlap components at a lower depth and components at a lower depth are under components at a higher depth. The relationship between components at the same depth is determined by their positions within the depth. For convenience, layered pane defines several layers within the possible range of depths for specific functions. For example, you can put a component on the highest layer, the drag layer, when dragging components.Swing provides two layered pane classes. The first,
JLayeredPane
, is the class that root panes use. The second,JDesktopPane
, is aJLayeredPane
subclass that's specialized for the task of holding internal frames. The example in this section uses an instance ofJLayeredPane
. For examples of usingJDesktopPane
, see How to Use Internal Frames.
Note: [PENDING: mention that layered panes don't work with internal frames in some releases of Swing?]
Every Swing container that has a root pane -- such as
JFrame
,JApplet
,JDialog
, andJInternalFrame
-- automatically has a layered pane, although many programs don't explicitly use the layered pane. [PENDING: link to high-level discussion of this] You can also create your own layered pane and use it anywhere you can use a regular Swing container.Here's a picture of a demo application that uses a layered pane to place colored labels on different layers:
Here's the code that creates and sets up the layered pane:
Try this:
- Compile and run the application. The source file is
LayeredPaneDemo.java
. You will also need thedukeWaveRed.gif
image file.
See Getting Started with Swing if you need help.- Move the mouse around in the lower part of the window. The image of Duke drags behind the Drag Layer and Popup layer labels and in front of the labels on the other three layers.
- Use the combo box at the top of the window to change Duke's layer. Use the check box to set whether Duke is in position 0 within the current layer.
This code creates a layered pane, gives it a preferred size and a border, and adds a mouse motion listener to it. Now let's look at the code that adds the colored labels to the layered pane at different depths.//Create the dragging area at the bottom of the window Dimension layeredPaneSize = new Dimension(300, 310); layeredPane = new JLayeredPane(); layeredPane.setPreferredSize(layeredPaneSize); layeredPane.setBorder(BorderFactory.createTitledBorder( "Move the Mouse to Move Duke")); layeredPane.addMouseMotionListener(new MouseMotionAdapter() { public void mouseEntered(MouseEvent e) { dragLabel.setBounds(e.getX()-15, e.getY()-10, iconWidth, iconHeight); } public void mouseMoved(MouseEvent e) { dragLabel.setBounds(e.getX()-15, e.getY()-10, iconWidth, iconHeight); } });Two statements are shown in bold font. The first sets the bounds of the label, which includes the label's x and y position as well as its width and height. You have to set each components x and y position explicitly because by default layered panes don't have a layout manager. You can set a layered pane's layout manager, but the layout manager will arrange the components as if they were all on one layer. Most programs use an intermediate container to contain and position components on the same layer, but use absolute positioning to layout components on different layers.//This is the origin of the default layer's label //and the size of all the layers' labels. Point origin = new Point(10, 20); Dimension size = new Dimension(140, 140); //For each layer, add a colored label overlapping the last for (int i = 0 ; i < layerValues.length; i++) { //Create and set up colored label JLabel label = new JLabel(/*text for label*/); ... //Position and size it the hard way label.setBounds(origin.x, origin.y, size.width, size.height); //Add it to the layered pane layeredPane.add(label, /*depth*/); //Adjust origin for next layer origin.x += 35; origin.y += 35; }The second bold statement adds the label to the layered pane and sets its depth. In this example, each colored label is added to a different layer. The
add
method used in this program takes two arguments: The first is the component to add; the second is anInteger
indicating the depth at which to put the component. You can use anyInteger
to specify depth. However, this example and most other programs use one of those defined by theJLayeredPane
class:
Here's the code that creates the label with Duke's image and adds it to the layered pane:
Layer Name Value Description FRAME_CONTENT_LAYER
new Integer(-30000)
This layer is used to position the frame's content pane and menu bar. Most programs won't use this. DEFAULT_LAYER
new Integer(0)
Most components go in this layer. PALETTE_LAYER
new Integer(100)
This layer is useful for floating toolbars and palettes. MODAL_LAYER
new Integer(200)
Modal dialogs, such as those provided by JOptionPane
, belong in this layer.POPUP_LAYER
new Integer(300)
Popups go in this layer because they need to appear above just about everything. DRAG_LAYER
new Integer(400)
Move a component to this layer when dragging. Return the component to its regular layer when dropped. Note that this code uses a three argument version of the//Create and add the drag label (duke image) to the layered pane dragLabel = new JLabel(icon); dragLabel.setBounds(15, 225, iconWidth, iconHeight); layeredPane.add(dragLabel, JLayeredPane.MODAL_LAYER, 0);add
method. The third argument specifies the Duke label's position within its layer which determines its relationship with other components at the same depth. Positions are specified with anint
between -1 and (N-1), where N is the number of components at the depth. Unlike layer numbers, the lower 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. Both a component's layer and its relative position within its layer can change. In the example, the combo box changes Duke's layer and the check box changes Duke's position within the layer. The check box and the combo box share the same action listener, which has thisactionPerformed
method:When the user chooses a new layer with the combo box, the code changes Duke's layer by using thepublic void actionPerformed(ActionEvent e) { //event came from the combo box...change Duke's layer if (e.getSource().equals(layerList)) layeredPane.setLayer(dragLabel, layerValues[layerList.getSelectedIndex()].intValue(), onTop.isSelected()?0:1); //event came from the combo box...change Duke's layer else { if (onTop.isSelected()) layeredPane.moveToFront(dragLabel); else layeredPane.moveToBack(dragLabel); } }setLayer
method. This version ofsetLayer
requires a position as well. The code computes the position value based on the check box's selected state.JLayeredPane
provides a two-argument version ofsetLayer
that requires only the component and layer. Use that method if you want the components to be positioned based on the order in which they were added to the layered pane (last on top, first on bottom). When the user selects the check box, themoveToFront
method moves Duke to the front (position 0). And when the user deselects check box, Duke gets moved to the back with themoveToBack
method.
A Note of Caution: When adding a component to a layered pane you specify the layer with anInteger
. When usingsetLayer
to change a component's layer, you use anint
. Use the API tables below to check the types of the arguments and return values for other methods in this class that deal with layers.
The Layered Pane API
The following tables list the commonly usedJLayeredPane
constructors and methods. Other methods you're likely to call are defined by theJComponent
andComponent
classes and include [PENDING: anything in particular for JLayeredPane?]. [Link to JComponent and Component discussions.]The API for using layered pane falls into these categories:
Creating or Getting a Layered Pane Method Purpose JLayeredPane()
Create a layered pane. JLayeredPane getLayeredPane()
(inJApplet
,JDialog
,JFrame
, andJInternalFrame
)Get the layered pane in an applet, dialog, frame, or internal frame.
Layering Components Method Purpose void add(Component, Integer)
void add(Component, Integer, int)Add the specified component to the layered pane. The second argument indicates the layer. The third argument, when present, indicates the component's position within its 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.
Setting Components' Intra-Layer Positions 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. Examples that Use Layered Panes
This table shows the examples that useJLayeredPane
and where those examples are described.
Example Where Described Notes LayeredPaneDemo.java
This page. Illustrates layers and intra-layer positions of a JLayeredPane
.InternalFrameDemo.java
How to Use Internal Frames Uses a JDesktopFrame
to manage internal frames.
Using Swing Components |