Download the JDK
Search the Tutorials
Hide the TOC
Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Section: How to Use GroupLayout
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
A GroupLayout Example

> As an example of GUI creation with `GroupLayout`, let's create a layout for this "Find" dialog box:

> ### Horizontal layout

> Examining the horizontal dimension from left to right, we can see there are 3 groups in a sequence. The first one is actually not a group, just a component -- the label. The second one is a group containing the text field and the check boxes (we'll decompose it later). And the third is a group of the two buttons. As illustrated here:

> Let's sketch out the sequential group in code. Note that `GroupLayout.Alignment.LEADING` corresponds to left alignment in the horizontal dimension. Also note we don't specify gaps, assuming the gap auto-insertion feature is turned on.

> >     layout.setHorizontalGroup(layout.createSequentialGroup()
> >         .addComponent(label)
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
> >     );

> Now let's decompose the group in the middle. This is the hardest one. There's a text field in parallel with a sequence of two parallel groups each containing two check boxes. See the following illustration:

> Let's add the corresponding code:

> >     layout.setHorizontalGroup(layout.createSequentialGroup()
> >         .addComponent(label)
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >              .addComponent(textField)
> >              .addGroup(layout.createSequentialGroup()
> >                   .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >                       .addComponent(caseCheckBox)
> >                       .addComponent(wholeCheckBox))
> >                   .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >                       .addComponent(wrapCheckBox)
> >                       .addComponent(backCheckBox))))
> >          .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
> >     );

> We want the text field to be resizable, but that happens automatically since `JTextField` returns the right maximum size by default.

> The remaining group on the right is trivial: it contains just two buttons. Here's the code:

> >     layout.setHorizontalGroup(layout.createSequentialGroup()
> >         .addComponent(label)
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >             .addComponent(textField)
> >             .addGroup(layout.createSequentialGroup()
> >                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >                     .addComponent(caseCheckBox)
> >                     .addComponent(wholeCheckBox))
> >                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >                     .addComponent(wrapCheckBox)
> >                     .addComponent(backCheckBox))))
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >             .addComponent(findButton)
> >             .addComponent(cancelButton))
> >     );

> And finally, we'd like the buttons to have always the same size, so let's link them:

> >     layout.linkSize(SwingConstants.HORIZONTAL, findButton, cancelButton);

> Now we are done with the horizontal dimension. Let's switch to the vertical dimension. From now, we'll only need to think about the y axis.

> ### Vertical layout

> In the vertical dimension, we examine the layout from top to bottom. We definitely want all the components on the first line aligned on baseline. So along the vertical axis there is a sequence of the baseline group, followed by a group of the remaining components. See the following picture.

> Let's sketch out the code. First, we need to define two parallel groups. Note that `GroupLayout.Alignment.LEADING` corresponds to the top alignment in the vertical dimension.

> >     layout.setVerticalGroup(layout.createSequentialGroup()
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE))
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
> >     );

> We can fill the baseline group right away:

> >     layout.setVerticalGroup(layout.createSequentialGroup()
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
> >             .addComponent(label)
> >             .addComponent(textField)
> >             .addComponent(findButton))
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
> >     );

> Now let's look at the bottom group. Note the Cancel button is not on a shared baseline with the check boxes; it is aligned at the top. So the second parallel group comprises the button and a sequential group of two baseline groups with check boxes:

> The corresponding code looks as follows:

> >     layout.setVerticalGroup(layout.createSequentialGroup()
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
> >             .addComponent(label)
> >             .addComponent(textField)
> >             .addComponent(findButton))
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >             .addGroup(layout.createSequentialGroup()
> >                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
> >                     .addComponent(caseCheckBox)
> >                     .addComponent(wrapCheckBox))
> >                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
> >                     .addComponent(wholeCheckBox)
> >                     .addComponent(backCheckBox)))
> >             .addComponent(cancelButton))
> >     );

> So, we've created a complete layout, including resize behavior, without specifying a single number in pixels—a true cross platform layout. Note that we don't need to specify gaps between components, we get correct spacing automatically and according to the look and feel guidelines. Here's the complete code for the Find dialog's layout:

> >     GroupLayout layout = new GroupLayout(getContentPane());
> >     getContentPane().setLayout(layout);
> >     layout.setAutocreateGaps(true);
> >     layout.setAutocreateContainerGaps(true);

> >     layout.setHorizontalGroup(layout.createSequentialGroup()
> >         .addComponent(label)
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >             .addComponent(textField)
> >             .addGroup(layout.createSequentialGroup()
> >                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >                     .addComponent(caseCheckBox)
> >                     .addComponent(wholeCheckBox))
> >                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >                     .addComponent(wrapCheckBox)
> >                     .addComponent(backCheckBox))))
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >             .addComponent(findButton)
> >             .addComponent(cancelButton))
> >     );
> >     layout.linkSize(SwingConstants.HORIZONTAL, findButton, cancelButton);

> >     layout.setVerticalGroup(layout.createSequentialGroup()
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
> >             .addComponent(label)
> >             .addComponent(textField)
> >             .addComponent(findButton))
> >         .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
> >             .addGroup(layout.createSequentialGroup()
> >                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
> >                     .addComponent(caseCheckBox)
> >                     .addComponent(wrapCheckBox))
> >                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
> >                     .addComponent(wholeCheckBox)
> >                     .addComponent(backCheckBox)))
> >             .addComponent(cancelButton))
> >     );

> Here is the complete `Find.java` file. You can compile and run it. Try resizing the dialog horizontally to see how the layout automatically adjusts to the new size.

« Previous • Trail • Next »
Previous page: How to Use GroupLayout
Next page: How to Use SpringLayout