Perfect layouts are those in which each component is always displayed at its preferred size, the containing window is sized precisely to be just the size to hold the components, and the containing window does not allow (or does not need) resizing. There are one or two exceptions to displaying the components at the preferred size. One is command buttons, in that groups of command buttons look best when the buttons are aligned and all are the same size. A perfect layout compensates for this desired layout by choosing the button with the largest preferred size and making all other buttons in the group the same size as that button. The other exception is text components, which tend to have a preferred size that is inadequate for human users to perform text entry. Text components should be stretched to align visually with other components and to present a large enough area for the user to enter text.
Stretchable layouts are those in which it is desirable for some or all of the components in the container to be able to resize as the container resizes. An example is a window that contains a text area. It may be desirable for the text area to grow larger to display more text as the window is made larger. Other examples of components that might want to stretch to allow the user to see more of its contents are lists and trees. Usually a stretchable layout has some components that do not want to be stretched, such as command buttons, so a stretchable layout needs to be able to accomodate these kinds of components as well.
KappaLayout is the best choice for a perfect layout as it pays close attention to the preferred sizes of components. It can cause a component to be stretched for particular purposes, as in the example of command buttons that should be the same size. KappaLayout only allows components to be stretched once during initial layout, thereafter, the component does not change size regardless of size changes in the parent container.
LambdaLayout is the best choice for a stretchable layout as it allows components to stretch or shrink as the parent container is resized. LambdaLayout also pays close attention to the preferred sizes of components and will not allow components to be shrunk to less than the preferred size.
Often there are parts of a layout that should be stretchable and parts that should not. In these cases, a combination of the two layout managers should be used along with the nested panels technique.
The following code example shows how to construct the "Find" dialog as shown in Figure 30 of the Java Look and Feel Design Guidelines. This is a 'perfect' layout. The dialog is designed using the design grid method. This figure shows what the dialog will look like when displayed and the design parameters for laying out the components. The red lines are KappaLayout struts and are invisible in the displayed dialog. These struts are rigid, that is, they set the width or height of the column or row to a fixed size. Four of the columns from the design grid are not necessary so are not used. Columns and rows are numbered and are used to set the constraints for each component.
import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; /* This displays a "find" dialog as is shown in Figure 30 in the Java Look and Feel Design Guidelines. This class shows how to use KappaLayout to create this layout while conforming exactly to the guidelines. */ public class Figure30 { public Figure30() { // set up a JFrame JFrame f = new JFrame("Figure30"); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent we) { f.dispose(); } }); /* create the content pane and its layout manager. Use our own JPanel rather than the default container so we can set a javax.swing.border and use a KappaLayout rather than the default BorderLayout (the default content pane for a JFrame uses a BorderLayout. In fact, the default content pane is a JPanel, but would need to be cast as such to be useable as a JPanel.) */ KappaLayout kl = new KappaLayout(); JPanel contents = new JPanel(kl); f.setContentPane(contents); /* set an EmptyBorder on our content panel to create the desired blank space around the contained components. See text accompanying Figure 76 in the Java Look and Feel Guidelines -- the guideline is 12 pixels spacing on top and left, 11 pixels on right and bottom. The EmptyBorder does this nicely. An alternate method (suitable for AWT only layouts) is to override the getInsets method. Panel contents = new Panel(kl) { Insets insets = new Insets(12, 12, 11, 11); public Insets getInsets() { return insets; } }; KappaLayout is one of the few layout managers that respect the insets of a container. */ contents.setBorder(new EmptyBorder(12, 11, 11, 12)); /* add the components, following the design grid. Constraint string follows this pattern: "x, y, w, h, a, s, p" where x is start column of component y is start row of component w is width of component in columns h is height of component in rows a is alignment in cell s is stretch parameter p is padding around component in pixels All parameters have defaults and all parameters are optional. See KappaLayout documentation for details of the constraint string. */ // align label to right side of cell contents.add(new JLabel("Find:"), "0, 0, 1, 1, 3"); // stretch text field to fit across 3 columns contents.add(new JTextField(), "2, 0, 3, 1, 0, w"); // align check boxes and radio buttons to left side of cell contents.add(new JCheckBox("Match Case"), "2, 2, 1, 1, 7"); contents.add(new JCheckBox("Whole Word"), "2, 3, 1, 1, 7"); contents.add(new JRadioButton("Start at Top"), "4, 2, 1, 1, 7"); contents.add(new JRadioButton("Wrap Around"), "4, 3, 1, 1, 7"); /* add some struts to ensure fixed separation between components follows the guidelines: 11 pixels between groups, 17 between bottom group and command buttons. */ // strut to separate textfield and top checkbox contents.add(KappaLayout.createVerticalStrut(11, true), "0, 1"); // strut to separate "Find:" label and textfield contents.add(KappaLayout.createHorizontalStrut(11, true), "1, 1"); // strut to separate checkbox column and radio button column contents.add(KappaLayout.createHorizontalStrut(11, true), "3, 1"); // strut to separate bottom checkbox and command buttons contents.add(KappaLayout.createVerticalStrut(17, true), "0, 4"); /* use a separate panel for the buttons to properly align the buttons across the correct grids. This panel can stretch to the full width of the dialog, so will fit regardless of the text on the buttons. */ KappaLayout kl2 = new KappaLayout(); JPanel btn_panel = new JPanel(kl2); // stretch button to fill full width of cell btn_panel.add(new JButton("Find"), "0, 0, 1, 1, , w"); // guidelines say to use 5 pixels between buttons btn_panel.add(KappaLayout.createHorizontalStrut(5), "1, 0, 1, 1"); // stretch button to fill full width of cell btn_panel.add(new JButton("Close"), "2, 0, 1, 1, , w"); /* make the 2 columns holding the buttons the same width. KappaLayout finds the button with the widest preferred width, and uses that width for both columns. The 'w' parameter used in laying out the buttons lets the button with the smaller width of the 2 stretch to be the same size. This is exactly the layout specified by the guidelines. */ kl2.makeColumnsSameWidth(0, 2); /* add the button panel, Allow the panel to fill the full width of the dialog if needed, but align it to the right side and bottom of the dialog as required by the guidelines */ contents.add(btn_panel, "0, 5, 5, 1, 4"); /* pack and show -- this is a 'perfect' dialog, that is, all components are laid out at their preferred size (or, in the case of the buttons, at the same size as the largest preferred size in the button group), inter-component spacing is fixed, and there is no need to stretch any component when resizing the dialog, so set the dialog to disallow resizing. */ f.setResizable(false); f.pack(); f.show(); } public static void main(String[] args) { new Figure30(); } }
The full Java Look and Feel Design guidelines can be found at:
http://java.sun.com/products/jlf/guidelines.html
The full guidelines cover quite a lot of material that does not directly apply to laying out user interfaces, so I've compiled an abbreviated guideline containing just the rules for how a user interface should be constructed. The abbreviated guidelines can be found at:
http://ise.fdns.net/freestuff/layouts/docs/guidelines.html
Documentation for both KappaLayout and LambdaLayout can be found at:
http://ise/fdns.net/freestuff/layouts/docs/
An excellent reference for constructing usable interfaces is "Software for Use" by Larry Constantine and Lucy Lockwood. See http://www.foruse.com for details.