Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 14

Download the JDK

Search the Tutorials


Hide the TOC
Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
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 »
Using Layout Managers
A layout manager is an object that implements the LayoutManager interface* and determines the
size and position of the components within a container. Although components can provide size
and alignment hints, a container's layout manager has the final say on the size and position of the
components within the container.

Note: This lesson covers writing layout code by hand, which can be challenging. If you are not
interested in learning all the details of layout management, you might prefer to use the
GroupLayout layout manager combined with a builder tool to lay out your GUI. One such
builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use
GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful
layout manager.

This section discusses some of the common tasks related to using layout managers:

 Setting the Layout Manager


 Adding Components to a Container
 Providing Size and Alignment Hints
 Putting Space Between Components
 Setting the Container's Orientation
 Tips on Choosing a Layout Manager
 Third-Party Layout Managers

Setting the Layout Manager

As a rule, the only containers whose layout managers you need to worry about are JPanels and
content panes. Each JPanel object is initialized to use a FlowLayout, unless you specify
differently when creating the JPanel. Content panes use BorderLayout by default. If you do not
like the default layout manager that a panel or content pane uses, you are free to change it to a
different one. However, unless you are using JToolBar, the FlowLayout and BorderLayout
managers are only useful for prototyping. Any real application will need to reset the layout
manager. Again, you should use an appropriate tool to do this, rather than coding the manager by
hand.

You can set a panel's layout manager using the JPanel constructor. For example:

JPanel panel = new JPanel(new BorderLayout());


After a container has been created, you can set its layout manager using the setLayout method.
For example:
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());

Although we strongly recommend that you use layout managers, you can perform layout without
them. By setting a container's layout property to null, you make the container use no layout
manager. With this strategy, called absolute positioning, you must specify the size and position
of every component within that container. One drawback of absolute positioning is that it does
not adjust well when the top-level container is resized. It also does not adjust well to differences
between users and systems, such as different font sizes and locales.

Adding Components to a Container

When you add components to a panel or content pane, the arguments you specify to the add
method depend on the layout manager that the panel or content pane is using. In fact, some
layout managers do not even require you to add the component explicitly; for example,
GroupLayout. For example, BorderLayout requires that you specify the area to which the
component should be added (using one of the constants defined in BorderLayout) using code
like this:
pane.add(aComponent, BorderLayout.PAGE_START);

The how-to section for each layout manager has details on what, if any, arguments you need to
specify to the add method. Some layout managers, such as GridBagLayout and SpringLayout,
require elaborate setup procedures. Many layout managers, however, simply place components
based on the order they were added to their container.
Swing containers other than JPanel and content panes generally provide API that you should use
instead of the add method. For example, instead of adding a component directly to a scroll pane
(or, actually, to its viewport), you either specify the component in the JScrollPane constructor
or use setViewportView. Because of specialized API like this, you do not need to know which
layout manager (if any) many Swing containers use. (For the curious: scroll panes happen to use
a layout manager named ScrollPaneLayout.)

For information about how to add components to a specific container, see the how-to page for
the container. You can find the component how-to pages using How to Use Various
Components.

Providing Size and Alignment Hints

Sometimes you need to customize the size hints that a component provides to its container's
layout manager, so that the component will be laid out well. You can do this by specifying one or
more of the minimum, preferred, and maximum sizes of the component. You can invoke the
component's methods for setting size hints — setMinimumSize, setPreferredSize, and
setMaximumSize. Or you can create a subclass of the component that overrides the appropriate
getter methods — getMinimumSize, getPreferredSize, and getMaximumSize. Here is an
example of making a component's maximum size unlimited:
component.setMaximumSize(new Dimension(Integer.MAX_VALUE,
Integer.MAX_VALUE));

Many layout managers do not pay attention to a component's requested maximum size. However,
BoxLayout and SpringLayout do. Furthermore, GroupLayout provides the ability to set the
minimum, preferred or maximum size explicitly, without touching the component.

Besides providing size hints, you can also provide alignment hints. For example, you can specify
that the top edges of two components should be aligned. You set alignment hints either by
invoking the component's setAlignmentX and setAlignmentY methods, or by overriding the
component's getAlignmentX and getAlignmentY methods. Although most layout managers
ignore alignment hints, BoxLayout honors them. You can find examples of setting the alignment
in How to Use BoxLayout.

Putting Space Between Components

Three factors influence the amount of space between visible components in a container:
The layout manager
Some layout managers automatically put
space between components; others do not.
Some let you specify the amount of space
between components. See the how-to page
for each layout manager for information
about spacing support.
Invisible components
You can create lightweight components that
perform no painting, but that can take up
space in the GUI. Often, you use invisible
components in containers controlled by
BoxLayout. See How to Use BoxLayout for
examples of using invisible components.
Empty borders
No matter what the layout manager, you can
affect the apparent amount of space between
components by adding empty borders to
components. The best candidates for empty
borders are components that typically have
no default border, such as panels and labels.
Some other components might not work
well with borders in some look-and-feel
implementations, because of the way their
painting code is implemented. For
information about borders, see How to Use
Borders.

Setting the Container's Orientation

This website is written in English, with text that runs from left to right, and then top to bottom.
However, many other languages have different orientations. The componentOrientation
property provides a way of indicating that a particular component should use something different
from the default left-to-right, top-to-bottom orientation. In a component such as a radio button,
the orientation might be used as a hint that the look and feel should switch the locations of the
icon and text in the button. In a container, the orientation is used as a hint to the layout manager.

To set a container's orientation, you can use either the Component-defined method
setComponentOrientation or, to set the orientation on the container's children as well,
applyComponentOrientation. The argument to either method can be a constant such as
ComponentOrientation.RIGHT_TO_LEFT, or it can be a call to the ComponentOrientation
method getOrientation(Locale). For example, the following code causes all JComponents to
be initialized with an Arabic-language locale, and then sets the orientation of the content pane
and all components inside it accordingly:

JComponent.setDefaultLocale(new Locale("ar"));
JFrame frame = new JFrame();
...
Container contentPane = frame.getContentPane();
contentPane.applyComponentOrientation(
ComponentOrientation.getOrientation(
contentPane.getLocale()));
Here are two pictures showing how FlowLayout lays out components in containers that are
exactly the same, except for their orientation.
Default orientation (left-to-right)

Right-to-left orientation

The standard layout managers that support component orientation are FlowLayout,
BorderLayout, BoxLayout, GridBagLayout, and GridLayout.

Note: Care must be taken that the component orientation is applied to renderers, editors and any
other components unreachable through normal traversal of the containment hierarchy.

Tips on Choosing a Layout Manager

Layout managers have different strengths and weaknesses. This section discusses some common
layout scenarios and which layout managers might work for each scenario. However, once again,
it is strongly recommended that you use a builder tool to create your layout managers, such as
the NetBeans IDE 5.5 Matisse GUI builder, rather than coding managers by hand. The scenarios
listed below are given for information purposes, in case you are curious about which type of
manager is used in different situations, or in case you absolutely must code your manager
manually.

If none of the layout managers we discuss is right for your situation and you cannot use a builder
tool, feel free to use other layout managers that you may write or find. Also keep in mind that
flexible layout managers such as GridBagLayout and SpringLayout can fulfill many layout
needs.

Scenario: You need to display a component in as much space as it can get.


If it is the only component in its container,
use GridLayout or BorderLayout.
Otherwise, BorderLayout or
GridBagLayout might be a good match.

If you use BorderLayout, you will need to


put the space-hungry component in the
center. With GridBagLayout, you will need
to set the constraints for the component so
that fill=GridBagConstraints.BOTH.
Another possibility is to use BoxLayout,
making the space-hungry component specify
very large preferred and maximum sizes.

Scenario: You need to display a few components in a compact row at their natural size.
Consider using a JPanel to group the
components and using either the JPanel's
default FlowLayout manager or the
BoxLayout manager. SpringLayout is also
good for this.
Scenario: You need to display a few components of the same size in rows and columns.
GridLayout is perfect for this.
Scenario: You need to display a few components in a row or column, possibly with varying
amounts of space between them, custom alignment, or custom component sizes.
BoxLayout is perfect for this.
Scenario: You need to display aligned columns, as in a form-like interface where a column of
labels is used to describe text fields in an adjacent column.
SpringLayout is a natural choice for this.
The SpringUtilities class used by several
Tutorial examples defines a
makeCompactGrid method that lets you
easily align multiple rows and columns of
components.
Scenario: You have a complex layout with many components.
Consider either using a very flexible layout
manager such as GridBagLayout or
SpringLayout, or grouping the components
into one or more JPanels to simplify layout.
If you take the latter approach, each JPanel
might use a different layout manager.

How Layout Management Works

Note: This lesson covers writing layout code by hand, which can be challenging. If you are not
interested in learning all the details of layout management, you might prefer to use the
GroupLayout layout manager combined with a builder tool to lay out your GUI. One such
builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use
GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful
layout manager.

Here is an example of a layout management sequence for a container using LayoutManager2.

1. Layout managers basically do two things:


o Calculate the
minimum/preferred/maximum sizes
for a container.
o Lay out the container's children.

Layout managers do this based on the


provided constraints, the container's
properties (such as insets) and on the
children's minimum/preferred/maximum
sizes. If a child is itself a container then its
own layout manger is used to get its
minimum/preferred/maximum sizes and to
lay it out.

2. A container can be valid (namely,


isValid() returns true) or invalid. For a
container to be valid, all the container's
children must be laid out already and must
all be valid also. The Container.validate
method can be used to validate an invalid
container. This method triggers the layout
for the container and all the child containers
down the component hierarchy and marks
this container as valid.
3. After a component is created it is in the
invalid state by default. The Window.pack
method validates the window and lays out
the window's component hierarchy for the
first time.

The end result is that to determine the best size for the container, the system determines the sizes
of the containers at the bottom of the containment hierarchy. These sizes then percolate up the
containment hierarchy, eventually determining the container's total size.

If the size of a component changes, for example following a change of font, the component must
be resized and repainted by calling the revalidate and repaint methods on that component.
Both revalidate and repaint are thread-safe — you need not invoke them from the event-
dispatching thread.

When you invoke revalidate on a component, a request is passed up the containment hierarchy
until it encounters a container, such as a scroll pane or top-level container, that should not be
affected by the component's resizing. (This is determined by calling the container's
isValidateRoot method.) The container is then laid out, which has the effect of adjusting the
revalidated component's size and the size of all affected components.

How to Use Panels


The JPanel class provides general-purpose containers for lightweight components. By default,
panels do not add colors to anything except their own background; however, you can easily add
borders to them and otherwise customize their painting. Details can be found in Performing
Custom Painting.

In many types of look and feel, panels are opaque by default. Opaque panels work well as
content panes and can help with painting efficiently, as described in Using Top-Level
Containers. You can change a panel's transparency by invoking the setOpaque method. A
transparent panel draws no background, so that any components underneath show through.

An Example

The following picture shows a colored version of the Converter application, which is discussed
in more detail in Using Models.

The Converter example uses panels in several ways:

 One JPanel instance — colored red in the


preceding snapshot — serves as a content
pane for the application's frame. This
content pane uses a top-to-bottom
BoxLayout to lay out its contents, and an
empty border to put 5 pixels of space around
them. See Using Top-Level Containers for
information about content panes.
 Two instances of a custom JPanel subclass
named ConversionPanel — colored cyan
— are used to contain components and
coordinate communication between
components. These ConversionPanel
panels also have titled borders, which
describe their contents and enclose the
contents with a line. Each
ConversionPanel panel uses a left-to-right
BoxLayout object to lay out its contents.
 In each ConversionPanel, a JPanel
instance — colored magenta — is used to
ensure the proper size and position of the
combo box. Each of these JPanel instances
uses a top-to-bottom BoxLayout object
(helped by an invisible space-filling
component) to lay out the combo box.
 In each ConversionPanel, an instance of an
unnamed JPanel subclass — colored blue
— groups two components (a text field and
a slider) and restricts their size. Each of
these JPanel instances uses a top-to-bottom
BoxLayout object to lay out its contents.

Here is what the Converter application normally looks like.

As the Converter example demonstrates, panels are useful for grouping components,
simplifying component layout, and putting borders around groups of components. The rest of
this section gives hints on grouping and laying out components. For information about using
borders, see How to Use Borders.

Setting the Layout Manager

Like other containers, a panel uses a layout manager to position and size its components. By
default, a panel's layout manager is an instance of FlowLayout, which places the panel's contents
in a row. You can easily make a panel use any other layout manager by invoking the setLayout
method or by specifying a layout manager when creating the panel. The latter approach is
preferable for performance reasons, since it avoids the unnecessary creation of a FlowLayout
object.

Here is an example of how to set the layout manager when creating the panel.

JPanel p = new JPanel(new BorderLayout()); //PREFERRED!


This approach does not work with BoxLayout, since the BoxLayout constructor requires a pre-
existing container. Here is an example that uses BoxLayout.

JPanel p = new JPanel();


p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));

Adding Components

When you add components to a panel, you use the add method. Exactly which arguments you
specify to the add method depend on which layout manager the panel uses. When the layout
manager is FlowLayout, BoxLayout, GridLayout, or SpringLayout, you will typically use the
one-argument add method, like this:
aFlowPanel.add(aComponent);
aFlowPanel.add(anotherComponent);
When the layout manager is BorderLayout, you need to provide an argument specifying the
added component's position within the panel. For example:
aBorderPanel.add(aComponent, BorderLayout.CENTER);
aBorderPanel.add(anotherComponent, BorderLayout.PAGE_END);
With GridBagLayout you can use either add method, but you must somehow specify grid bag
constraints for each component.

For information about choosing and using the standard layout managers, see Using Layout
Managers.

The Panel API

The API in the JPanel class itself is minimal. The methods you are most likely to invoke on a
JPanel object are those it inherits from its superclasses — JComponent, Container, and
Component. The following tables list the API you are most likely to use, with the exception of
methods related to borders and layout hints. For more information about the API that all
JComponent objects can use, see The JComponent Class.

 Creating a JPanel
 Managing a Container's Components
 Setting or Getting the Layout Manager

Creating a JPanel
Constructor Purpose
Creates a panel. The LayoutManager parameter provides a layout
JPanel()
manager for the new panel. By default, a panel uses a FlowLayout to lay
JPanel(LayoutManager)
out its components.
Managing a Container's Components
Method Purpose
void add(Component) Adds the specified component to the panel. When present, the int
void add(Component, int) parameter is the index of the component within the container. By
void add(Component,
default, the first component added is at index 0, the second is at index
Object)
1, and so on. The Object parameter is layout manager dependent and
void add(Component,
typically provides information to the layout manager regarding
Object, int)
positioning and other layout constraints for the added component. The
void add(String,
String parameter is similar to the Object parameter.
Component)
int getComponentCount() Gets the number of components in this panel.
Component
getComponent(int)
Component
getComponentAt(int, int) Gets the specified component or components. You can get a
Component component based on its index or x, y position.
getComponentAt(Point)
Component[]
getComponents()
void remove(Component)
void remove(int) Removes the specified component(s).
void removeAll()
Setting or Getting the Layout Manager
Method Purpose
void Sets or gets the layout manager for this panel. The layout manager
setLayout(LayoutManager) is responsible for positioning the panel's components within the
LayoutManager getLayout() panel's bounds according to some philosophy.

Examples That Use Panels

Many examples contained in this lesson use JPanel objects. The following table lists a few.

Where
Example Notes
Described
Uses five panels, four of which use BoxLayout and one of which
Converter This section uses GridLayout. The panels use borders and, as necessary, size
and alignment hints to affect layout.
ListDemo
How to Use Uses a panel, with its default FlowLayout manager, to center
Lists three components in a row.
ToolBarDemo
How to Use Uses a panel as a content pane. The panel contains three
Tool Bars components, laid out by BorderLayout.
BorderDemo
How to Use Contains many panels that have various kinds of borders.
Borders Several panels use BoxLayout.
How to Use
BoxLayoutDemo Illustrates the use of a panel with Swing's BoxLayout manager.
BoxLayout

How to Use Password Fields


The JPasswordField class, a subclass of JTextField, provides specialized text fields for
password entry. For security reasons, a password field does not show the characters that the user
types. Instead, the field displays a character different from the one typed, such as an asterisk '*'.
As another security precaution, a password field stores its value as an array of characters, rather
than as a string. Like an ordinary text field, a password field fires an action event when the user
indicates that text entry is complete, for example by pressing the Enter button.

Here is a picture of a demo that opens a small window and prompts the user to type in a
password.

Click the Launch button to run PasswordDemo using Java™ Web Start (download JDK 6).
Alternatively, to compile and run the example yourself, consult the example index.

The password is "bugaboo". You can find the entire code for this program in
PasswordDemo.java. Here is the code that creates and sets up the password field:
passwordField = new JPasswordField(10);
passwordField.setActionCommand(OK);
passwordField.addActionListener(this);
The argument passed into the JPasswordField constructor indicates the preferred size of the
field, which is at least 10 columns wide in this case. By default a password field displays a dot
for each character typed. If you want to change the echo character, call the setEchoChar
method. The code then adds an action listener to the password field, which checks the value
typed in by the user. Here is the implementation of the action listener's actionPerformed
method:
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();

if (OK.equals(cmd)) { //Process the password.


char[] input = passwordField.getPassword();
if (isPasswordCorrect(input)) {
JOptionPane.showMessageDialog(controllingFrame,
"Success! You typed the right password.");
} else {
JOptionPane.showMessageDialog(controllingFrame,
"Invalid password. Try again.",
"Error Message",
JOptionPane.ERROR_MESSAGE);
}

//Zero out the possible password, for security.


Arrays.fill(input, '0');

passwordField.selectAll();
resetFocus();
} else ...//handle the Help button...
}

Security note: Although the JPasswordField class inherits the getText method, you should
use the getPassword method instead. Not only is getText less secure, but in the future it might
return the visible string (for example, "******") instead of the typed string.

To further enhance security, once you are finished with the character array returned by the
getPassword method, you should set each of its elements to zero. The preceding code snippet
shows how to do this.

A program that uses a password field typically validates the password before completing any
actions that require the password. This program calls a private method, isPasswordCorrect,
that compares the value returned by the getPassword method to a value stored in a character
array. Here is its code:

private static boolean isPasswordCorrect(char[] input) {


boolean isCorrect = true;
char[] correctPassword = { 'b', 'u', 'g', 'a', 'b', 'o', 'o' };

if (input.length != correctPassword.length) {
isCorrect = false;
} else {
isCorrect = Arrays.equals (input, correctPassword);
}

//Zero out the password.


Arrays.fill(correctPassword,'0');

return isCorrect;
}

The Password Field API

The following tables list the commonly used JPasswordField constructors and methods. For
information on the API that password fields inherit, see How to Use Text Fields.

Commonly Used JPasswordField Constructors and Methods


Constructor or Method Purpose
JPasswordField() Creates a password field. When present, the int
JPasswordField(String) argument specifies the desired width in columns. The
JPasswordField(String, int) String argument contains the field's initial text. The
JPasswordField(int) Document argument provides a custom model for the
JPasswordField(Document, String, int) field.
char[] getPassword() Returns the password as an array of characters.
void setEchoChar(char) Sets or gets the echo character which is displayed
char getEchoChar() instead of the actual characters typed by the user.
void addActionListener(ActionListener)
void
Adds or removes an action listener.
removeActionListener(ActionListener)
(defined in JTextField)
void selectAll()
Selects all characters in the password field.
(defined in JTextComponent)

Examples That Use Password Fields

PasswordDemo is the Tutorial's only example that uses a JPasswordField object. However, the
Tutorial has many examples that use JTextField objects, whose API is inherited by
JPasswordField. See Examples That Use Text Fields for further information.

You might also like