Search code examples
javaswingjlayeredpane

JLayeredPane: what's the functional difference between depth and position?


I am working on a Connect Four game for a school Java project. I've got the 'how' of the JLayeredPane, and it is working as expected, but I'm not quite getting the 'why' behind a certain concept.

Here is my understanding:

JLayeredPane is a container, similar to JPanel, that allows you to specify depth and position for each component. Depth is an Integer, with 0 being the bottom layer and n-1 being the top layer, with n being the number of components. Position is an int (yes, one uses the Integer wrapper class and one is just a primitive!) that specifies a component's postion within the layer, with 0 being the topmost layer, -1 being the bottom-most layer, and positive ints in between, the lower the number the higher the position. So, four components in a single layer could be ordered into position 0, 1, 2, -1 from topmost to bottom-most.

My question is, what's the need to have both concepts?

For instance, I have created three JLabels with images: a frontBoard, a backBoard, and a piece. The piece sometimes goes in front of the frontBoard and sometimes goes between the frontBoard and the backBoard. Let's examine the second example.

I can get the same effect through either of these means:

1) I can set the backBoard to layer 0, position 0; the piece to layer 1, position 0; and the frontBoard to layer 2, position 0

 or 

2) I can set the backBoard to layer 0, position -1; the piece to layer 0, position 1; and the frontBoard to layer 0, position 0

I have tested both of these ways, and I can't find a functional difference between the two methods.

Can anyone shed any light on this mystery for me?


Solution

  • First off, the best thing to do in such a case is have a look at the tutorial, they are usually very informative: http://download.oracle.com/javase/tutorial/uiswing/components/layeredpane.html

    Also, the javadoc of the class itself contains quite a good explanation of the way JLayeredPane works.

    Since you already implemented your project, you know that you can achieve stacking of components in two different ways: putting each component on its own layer, or by assigning different components that are on the same layer different position values. The effect is the same, but you would use two different properties to achieve it:

    • "depth" is a property of the layer: they are enumerated so that the layer with depth 0 is furthest the lowest of all. Layers with higher depths cover layers with lower depths.
    • Since layers can contain more than one component and since components can always overlap, there must be a way to define the z-order of the components within the layer: that is achieved by enumerating the components with a "position" value. If there are n components in the layer and you start counting at 0, then a position must be a value in the range between 0 and n-1.

    Now you could argue that since you have the "position" value, you don't need multiple layers at all, since you can position all components along the z-axis simply through their "position" value. That is true and nobody keeps you from doing so.

    The rationale for multiple layers can be seen when you realize that there a predefined constants to be used for the "depth" value of the layers:

    • DEFAULT_LAYER
    • PALETTE_LAYER
    • MODAL_LAYER
    • POPUP_LAYER
    • DRAG_LAYER

    These are are just logical groupings for complex multi-window applications that help you make sure that some stacking constraints are met: imagine you want to create a modal dialog window that appears on top of your main application frame. If you use a single layer, you must keep track of the positions of all visible components yourself and set the position of the dialog to n. Now add in drag and drop animations, popup menus, etc. and this task becomes quite complex.

    By using predefined layers this complexity is reduced. If you want to display a modal dialog window, you don't care about the components of the main application window, you just place it on the MODAL_LAYER and you're done: you can be certain that it's displayed on top of all other components.

    Luckily, Swing does all this stuff for you already (by using JLayeredPane or subclasses thereof internally), so you can just call setVisible(boolean) or setModal(boolean) on a JDialog and it will turn out the way you expect it to.