Swing Layout and Sizing
If you have worked with Swing you have surely heard yourself ask something like, “I set the preferred size of that component, why the hell isn’t it sizing it at that size, WTF???”. Swing layout and sizing is something that even experienced Java programmers suck at. I used to suck at it, until one day, years ago, I decided to figure out what the hell was going on. It turned out to be quite simple. There are just a few pieces of information you need to know to understand layout and sizing with Swing.
All layout and sizing of components are controlled by the layout managers and each layout manager will accept some hints on how to size components. Some of the layout managers readily accept the hints and try to honor them. Other layout managers seem to take some of your hints under advisement and then ignore others, still other layout managers look at your hints, laugh in your face, and lay out the components randomly (j/k) according to its predefined rules.
The hints you can pass to the layout manager come from three properties in the JComponent class that you set with their setter methods: setPreferredSize(), setMinimumSize(), and setMaximumSize(). The key piece of information to know is that it is up to each layout manager which of these methods it will honor.
First it is probably important to know what layout managers are available. As of Java 1.6 there are 7 layout managers that come with the JDK, they are:
- BorderLayout – The Default layout manager of top-level containers: JFrame, JDialog, JApplet, and the kind-of top-level container JInternalFrame. A perfect choice for all top-level containers, don’t change it unless you have some weird one-off use case
- BoxLayout – IMHO, the most useful layout manager available for all non top-level containers
- GridBagLayout – avoid like the plague, if you don’t take my advice and try to make a go of it you will find this humorous: http://madbean.com/anim/totallygridbag/
- FlowLayout – The default layout manager of JPanels. I find it unfortunate this is the default layout for JPanels as it is nearly worthless except for quick mockups. Do yourself a favor and immediately change your panel to use BoxLayout instead!
- CardLayout – Many people recommend using this one when you need to swap out one panel for another at runtime when the need arises. I have never found swapping out panels too terrbily difficult so have never used it
- GridLayout – Use when you want things in a grid with the exact same height and width, I have never used one, its use case is so limited I find it to be worthless
- GroupLayout – added in Java 1.6, primarily intended to be used by GUI builders
Here are the hints that each layout manager supports:
Layout Manager | Honors preferredSize? | Honors minimumSize | Honors maximumSize |
---|---|---|---|
BorderLayout | Partly (see BorderLayout extra notes) | No | No |
GridBagLayout | Yes | Yes | No |
FlowLayout | Yes | No | No |
CardLayout | Sort of (see Card and GridLayout extra notes) | No | No |
BoxLayout | X_AXIS–honors preferred width, Y_AXIS–honors preferred height | Yes | Yes |
GridLayout | Sort of (see Card and GridLayout extra notes) | No | No |
GroupLayout | Sequential Groups–Yes, Parallel Groups–Sort of (see GroupLayout extra notes) | Sequential Groups–Yes, Parallel Groups–No | Sequential Groups–Yes, Parallel Groups–No |
Use of the Hints
It should be noted that if you find yourself using these properties a lot you are doing something wrong. In practice, if you understand how the layout managers work, you will rarely need to use these. I recommend not using the hints at first, then if needed make some fine-adjustments with the hints.
BorderLayout Extra Notes
- NORTH and SOUTH components – respects component’s preferred height if possible, width is set to full available width of the container
- EAST and WEST components – respects component’s preferred width if possible, height is set to full available height of the container
- CENTER component – gets whatever space is left over, if any
CardLayout and GridLayout Extra Notes
Both CardLayout and GridLayout sizes all of the components in a container it is controlling to be the same size. It searches for the component with the largest preferred width and the component with the largest preferred height and sets all components to that preferred width and height. It should be noted that the maximum preferred height and width DO NOT have to come from the same component.
GroupLayout Extra Notes
Note that GroupLayout is really designed to be used by GUI builders. It can be hand coded but that wasn’t really what it was designed for. Anyway, parallel groups have some odd sizing rules and it is best to read about them straight from Oracle, (from:http://docs.oracle.com/javase/tutorial/uiswing/layout/group.html
The underlying mechanism works as follows:
1. The size of the parallel group is set to the preferred size of the largest element; so to the preferred size of c4 in our example.
1. Resizable elements are stretched to the size of the group. In our example, only c3 is effectively stretched, the size of c4 already corresponds to the size of the group.
Conclusion
Knowing this information should keep you from beating your head on your keyboard wondering why the hell the components aren’t appearing like you think they should. As a helpful hint to Swing newbies you can almost always achieve the layout you want by using BorderLayout for your top-level container (the default) and then using nested JPanels with BoxLayout. I rarely use anything other than BoxLayout for my JPanels.