MigLayout, how to make a panel float
By meverett | March 13, 2009
Take a look at the image below. There are three major components: a top header that spans the width, a left hand nav and a main panel that fills the remaining width and height. It would be pretty easy to lay out these three components using BorderLayout.
Now suppose we wanted to add a floating component over top of these. The idea is this floating component would be centered both vertically and horizontally regardless of how big the parent grew.
There are a few different ways to achieve this effect.
GlassPane: One way would be to use the GlassPane. Position the first three components using BorderLayout and then add the floating component in the GlassPane. This works but fails if the three components don’t fill the entire screen. It also prevents you from using the GlassPane for something else (like ghost dragging for example).
JXLayer: Another approach would be to use the JXLayer. This certainly works but is a bit code heavy for simple uses.
StackLayout : A third approach might be to use the StackLayout found in the SwingX jar. This is a relatively simple solution but has the downside of still needing to use three layout managers, one for the first three components, one for the floating component and finally the StackLayout to put the two together. This of course creates excess components for the sake of laying out components, something we would like to avoid.
Let’s solve this problem using MigLayout. As I mentioned in a previous post, MigLayout allows us to mix different types of layouts in the same manager. So we will use the docking layout to layout the top and left components, the grid layout for the center component, then relative positioning to layout the floating component. Here’s how the code looks:
setLayout(new MigLayout("gap 0, insets 0, fill"));
add(createFloatingPanel(), "pos 0.50al 0.5al");
add(createPanel("Top", Color.yellow), "dock north");
add(createPanel("Left", Color.red), "dock west");
add(createPanel("Center", Color.green), "grow");
That’s all it takes, five lines of code and no extra components. The most important features in the constructor is the use of the keyword “fill” which ensures that we take up all the space in the parent.
Let’s look at the docking components. Using the keyword “dock” along with “north” & “west” act like BorderLayout. Adding the north component first ensures that it fills the horizontal space rather than the west component filling the vertical space. We then add the center component using the generic grid layout with the keyword “grow”. This ensures that the center component will fill any remaining space.
The most interesting thing here is the pos .5al .5al. This tells the floating panel to ignore the grid positioning. Instead it aligns it 50% vertically and 50% horizontally within the parent container.
Five lines of code to again achieve a pretty impressive layout. Two important things to note here:
1) Notice that the floating panel is added first. If it’s added after the other components, it will be drawn behind them.
2) This technique won’t always work. If one of the components behind the floating panel is a JTable or JList which contains cell Renderers, then this layout method will fail.
In LW 5, we use this miglayout technique whenever there isn’t a table or list behind a floating component and use JXLayer to achieve the same effect when there is a table or list.

Comments and Trackbacks
tbee Says:
March 17th, 2009 at 3:03 am |
Permalink
About when this method fails; I assume that is because the cell being painted in the JTable or JList is then painted over the floating panel. Correct?
meverett Says:
March 17th, 2009 at 9:50 am |
Permalink
Yes that is exactly what happens. Depending on what table cells need rendering you may see the overlay component not appear, be partially painted or flicker.
Java desktops links of the week, March 23 | Jonathan Giles Says:
March 22nd, 2009 at 6:38 pm |
Permalink
[…] Limewire blog has a post about creating floating panels using the MigLayout […]
Kevin Narvaez Says:
March 24th, 2009 at 5:08 pm |
Permalink
Why not use the JLayeredPane that is in the component hierarchy of all JDialogs or JFrames? I appreciate that you will need to use absolute positioning instead of a layout manager in the layered pane but you can still use whatever layout manager you want for the content pane. This gives you multiple layers in which to place your floating panel and these do not interfere with the glass pane. The layered pane also avoids the painting issues of cell renderers below the layered pane. There is no need for the extra overhead of a library like JXLayer.
I have used this approach many times to create things like animated popups over all types of components including lists and tables without any painting artifacts.
meverett Says:
March 26th, 2009 at 3:29 pm |
Permalink
Hi Kevin,
You make some valid points about JLayeredPane.
The places that we use this Miglayout technique and similarly the JXLayer are much more complex layouts. I simplified the examples for clarity sake. Imagine the components in the examples above not filling the entire frame. There may be more components to the top, bottom, left, etc.. but we still want to restrict the floating panel to just the space filled by the same three underlying components that are shown above.
It’s still possible to achieve this same effect in JLayeredPane but this becomes much more complicated. In these more complex layouts there are two advantages over using just JLayeredPane, 1) In general this very nicely encapsulates subcomponents from the entire Frame, you don’t have to worry about multiple components trying to render in the same layer or hiding the layer if the underlying component gets hidden. and 2) there’s potential for less painting using these techniques given this encapsulation. When making changes in the JLayeredPane the entire frame may need to get repainted.