Exploring the AWT Layout Managers

   
   

Articles Index


This interactive article describes the Abstract Window Toolkit (AWT) predefined layout managers with text and a demonstration application. As you read about the different layout managers, you can play with the application to see for yourself how each AWT layout manager arranges components and behaves when the window resizes.

What is a Layout Manager?

A layout manager is an object that controls the size and position (layout) of components inside a Container object. For example, a window is a container that contains components such as buttons and labels. The layout manager in effect for the window determines how the components are sized and positioned inside the window.

A container can contain another container. For example, a window can contain a panel, which is itself a container. As you can see in the figure, the layout manager in effect for the window determines how the two panels are sized and positioned inside the window, and the layout manager in effect for each panel determines how components are sized and positioned inside the panels.

List of Layout Managers

The java.awt package provides the following predefined layout managers that implement the java.awt.LayoutManager interface. Every Abstract Window Toolkit (AWT) and Swing container has a predefined layout manager as its default. It is easy to use the container.setLayout method to change the layout manager, and you can define your own layout manager by implementing the java.awt.LayoutManager interface. This article describes the predefined AWT layout managers in this list.

The Java Development Kit (JDK) 1.2 introduces BoxLayout for placing components from left to right or top to bottom in an AWT or Swing container.

Demonstration

 

The best way to see how the AWT layout managers behave is to try them out. The demonstration application uses AWT components. You can view AWT and Swing versions of the source code for the demonstrationapplication in the Conclusion section at the end of this article.

Your browser cannot run applets. Here is a screen capture of what you would have seen:

When you select a layout manager from the left panel, the right panel displays components using the selected layout manager. If you resize the window, you will see how that layout manager handles the positioning of components during a window resize operation. The OK button on each right panel layout clears the right panel.

BorderLayout

 

The border layout is the default layout manager for all Window objects. It consists of five fixed areas: North, South, East, West, and Center. You do not have to put a component in every area of the border layout. The demonstration puts the label "Border Layout" in the North area, the OK button in the South area, and the List of fruit trees in the Center area. The East (right) and West (left) areas are empty.

The five areas of a border layout are shown at left. Notice how the North and South areas run like a header and footer across the panel.

If any or all of the North, South, East, or West areas are left out, the Central area spreads into the missing area or areas. However, if the Central area is left out, the North, South, East, or West areas do not change.

You can indent the Central area by placing a label with one or more blank characters in the East or West areas. The following code shows two ways to do it:

  Label label1 = new Label(" ");
  p2.add("East, label1);
  
  
  Label label2 = new Label();
  label2.setText(" ");
  p2.add("East", label2);

Here is the code for the border layout panel with the fruit tree list shown above:

  p2.setLayout(new BorderLayout());
  Label dialogLabel = new Label();
  dialogLabel.setAlignment(Label.CENTER);
  dialogLabel.setText("Border Layout");
  
  List items = new List(6, true);
  items.addItem("Apple tree");
  items.addItem("Orange tree");
  items.addItem("Pear tree");
  items.addItem("Peach tree");
  items.addItem("Cherry tree");
  items.addItem("Apricot tree");
  
  OK = new Button("OK");
  
  p2.add("North", dialogLabel);
  p2.add("South", OK);
  p2.add("Center", items);

Note that when using the BorderLayout, you must add components with either the add(String, Component) or the add(Component, Object) method to ensure the components are all added correctly. A common mistake people make is to use add(Component), which can result in some of the components not being visible.

To Layout Manager List

 

FlowLayout

 

The flow layout is the default layout manager for all Panel objects and applets. It places the panel components in rows according to the width of the panel and the number and size of the components. The best way to understand flow layout is to resize the demonstration window and notice how the components flow from one row to the other as you make the window wide and narrow.

Here is the code for the flow layout panel shown above:

  p2.setLayout(new FlowLayout());
  
p2.add(new Label("Flow Layout"));
OK = new Button("OK");
p2.add(new Button("An extremely long name"));
p2.add(new Button("Short"));
p2.add(new Button("Medium Length"));
p2.add(OK);
p2.add(new Scrollbar(Scrollbar.HORIZONTAL));

To Layout Manager List

 

CardLayout

 

The card layout lets you use one container (usually a panel) to display one out of many possible component children (like flipping cards on a table). A program can use this layout to show a different child component to different users. For example, the interface shown to an administrator might have additional functionality from the interface shown to a regular user. With card layout, your program can show the appropriate interface depending on the type of user using the program.

You can also use card layout to let your end user toggle among different displays and choose the one they prefer. In this case, the program must provide a GUI for the user to make the selection. The Choice component is commonly used for this case and the following card layout example shows how to use a Choice component to set up a card layout that lets the end user toggle between two interfaces.

Here is the code for the card layout panel shown above:

String BUTTONPANEL = 
 "Show panel with Buttons";
  String TEXTPANEL = 
   "Show panel with TextField";
  
  //Border layout is used to set the right panel up
  //with the Choice component 
  //and "Card Layout" label
  
    p2.setLayout(new BorderLayout());
  
  //The Choice component is put in a panel for 
  //better appearance
    Panel c2 = new Panel();
    Choice c = new Choice();
    c.addItem(BUTTONPANEL);
    c.addItem(TEXTPANEL);
    c2.add(c);
  
  //The Label is centered and put in the North area 
  //of the right panel
    Label cardLabel = new Label(
               "Card Layout");
    cardLabel.setAlignment(Label.CENTER);
    p2.add("North", cardLabel);
  
  //The choice is added to the 
  //Center area of the right panel
    p2.add("Center", c2);
  
  //The card panel is created and CardLayout used
    cards = new Panel();
    cards.setLayout(new CardLayout());
  
  //The two panels controlled by the card panel 
  //are created. 
    p3 = new Panel();
    p4 = new Panel();
  
  //The button components are created 
  //and added to p3
    OK = new Button("OK");
    Button quit = new Button("Cancel");
    reset = new Button("Reset");
    p3.add(OK);
    p3.add(quit);
    p3.add(reset);
  
  //The text field component is 
  //created and added to p4
    tfield = new TextField(
          "Enter name:", 20);
    p4.add(tfield);
  
  //Panels p3 and p3 are added to 
  //the card panel./c
    cards.add(BUTTONPANEL, p3);
    cards.add(TEXTPANEL, p4);
  
  //The card panel is added to the 
  //south area of the right panel
    p2.add("South", cards);

To Layout Manager List

 

GridLayout

 

The Grid layout arranges components into a grid of rows and columns. You specify the number of rows and columns, the number of rows only and let the layout manager determine the numer of columns, or the number of columns only and let the layout manager determine the number of rows.

The cells in the grid are equal size based on the largest component in the grid. Resize the window to see how the components are resized to fit cells as they get larger and smaller.

The grid layout demonstration starts with a one column grid, and lets you choose to see the same components in two, three, and four column grids.

Here is the code for the grid layout panel shown above.

  //Set grid to 5 rows and 1 column
    p2.setLayout(new GridLayout(5,1));
  
    two = new Button("2 cols.");
    three = new Button("3 cols.");
    four = new Button("4 cols.");
    OK = new Button("OK");
  
    p2.add(new Label(
        "Grid Layout     1 col."));
  
    p2.add(two);
    p2.add(three);
    p2.add(four);
    p2.add(OK);
  
  //Implement 2 column grid. 
  //Let layout manager determine number of rows.
    p2.setLayout(new GridLayout(0,2));
    two = new Button("2 cols.");
    three = new Button("3 cols.");
    four = new Button("4 cols.");
    OK = new Button("OK");
    p2.add(two);
    p2.add(three);
    p2.add(four);
    p2.add(OK);
  
  //Implement 3 column grid. 
  //Let layout manager determine number of rows.
    p2.setLayout(new GridLayout(0,3));
    two = new Button("2 cols.");
    three = new Button("3 cols.");
    four = new Button("4 cols.");
    OK = new Button("OK");
    p2.add(two);
    p2.add(three);
    p2.add(four);
    p2.add(OK);
  
  //Implement 4 column grid.
  //Let layout manager determine number of rows.
    p2.setLayout(new GridLayout(0,4));
    two = new Button("2 cols.");
    three = new Button("3 cols.");
    four = new Button("4 cols.");
    OK = new Button("OK");
    p2.add(two);
    p2.add(three);
    p2.add(four);
    p2.add(OK);

To Layout Manager List

 

GridBagLayout

 

The Grid bag layout (like grid layout) arranges components into a grid of rows and columns, but lets you specify a number of settings to fine-tune how the components are sized and positioned within the cells. Unlike the grid layout, the rows and columns are not constrained to be a uniform size. For example, a component can be set to span multiple rows or columns, or you can change its position on the grid.

The layout manager uses the number of components in the longest row, the number of rows created, and the size of the components to determine the number and size of the cells in the grid. The set of cells a component spans can be referred to as its display area. A component's display area and the way in which it fills that display area are defined by a set of constraints that are represented by the GridBagConstraints object. These constraints are the following, and will be described in the section on settings below:

  • gridx/gridy
  • gridwidth/gridheight
  • fill
  • anchor
  • ipadx/ipady
  • insets

The GridBagConstraints object is initialized with a set of default values, each of which can be customized to change the way the component will be layed out within the gridbag.

The following bulleted list outlines how to use the GridBagConstraints and GridBagLayout objects in code to achieve the look you want. This outline is for instructional purposes only and is used in the following code example. Once you understand how the objects work together, your code can, of course, do things in a different order or take another approach.

  • Decide how you want the components sized and positioned.
  • Create a GridBagLayout and GridBagConstraints object.
  • Have the container use the GridBagLayout object.
  • Customize the GridBagConstraints settings (or use defaults).
  • Create Component A.
  • Pass Component A and GridBagConstraints to the GridBagLayout object.
  • Add Component A to the container. The previous bullet told the container's layout which settings to use for the component.
  • Create Component B.
  • Change the GridBagConstraints settings or leave as is.
  • Pass Component B and GridBagConstraints to the GridBagLayout object.
  • Add Component B to the container.
  • and so on . . . .

Here is the code for the grid bag layout shown above.

  
//Create GridBagLayout and 
//GridBagConstraints objects.
  //Have container p2 use grid bag layout.
    GridBagConstraints c = 
    new GridBagConstraints();
    GridBagLayout gridbag = new GridBagLayout();
    p2.setLayout(gridbag);
  
  //Make components fill the available display area
  //in the horizontal and vertical directions
    c.fill = GridBagConstraints.BOTH;
  
  //Resize columns and keep them equal 
  //during window resizing 
  //Note: Since no weighty value is 
  //specified, rows are not resized,
  //but remain together in the middle of the 
  //display.
  //Test this by resizing the demonstration 
  //window with GridBag Layout selected.
    c.weightx = 1.0;
  
  //Create the Label component.
    Label top = new Label(
    "GridBag Layout");
    top.setAlignment(Label.CENTER);
  
  //Make the Label 
  component the last one in its row. 
    c.gridwidth = GridBagConstraints.REMAINDER;
  
  //Pass the Label component and 
  //GridBagConstraints object to layout.
    gridbag.setConstraints(top, c);
  
  //Add the Label component to container p2. 
  //The GridBagConstraints
  //passed to the GridBagLayout object for 
  //this container put the 
  //label in a row by itself, size the label 
  //to fill the row in the 
  //horizontal and vertical directions, and  
  //cause columns to resize
  //equally when the window is resized.
    p2.add(top);
  
  //Create a Text Field component.
    TextField name = new TextField(
            "Name:", 25);
  
  //Make the Text Field component the next 
  //to last one in its row.
  //This means 1 or more components can be added 
  //to the row after 
  //the Text field component.
    c.gridwidth = GridBagConstraints.RELATIVE;
  
  //Pass the Text Field component and 
  //GridBagConstraints object to layout.
    gridbag.setConstraints(name, c);
  
  //Add the Text Field component to 
  //container p2.
    p2.add(name);
  
  //Create another Text Field component.
    TextField addr = new TextField(
        "Address:", 25);
  
  //Make the Text field component the 
  //last one in its row.
    c.gridwidth = GridBagConstraints.REMAINDER;
  
  //Pass the Text Field component and 
  //GridBagConstraints object to layout.
    gridbag.setConstraints(addr, c);
  
  //Add the Text Field component to container p2.
    p2.add(addr);
  
  //Create a Text Area component.
    TextArea comments = new TextArea(3, 25);
    comments.setEditable(true);
    comments.setText("Comments:");
  
  //Pass the Text Area component and 
  //GridBagConstraints object to layout.
  //Because GridBagConstraints are unchanged, 
  //the Text Area component
  //is in a row by itself.
    gridbag.setConstraints(comments, c);
  
  //Add the Text Area component to container p2.
    p2.add(comments);
  
  //Create the OK and Cancel buttons.
    OK = new Button("OK");
    cancel = new Button("Cancel");
  
  //Make the OK button the next to last 
  //one in its row.
  //Components should not expand to fill 
  //the row in either
  //the horizontal or vertical direction.
    c.fill = GridBagConstraints.NONE;
    c.gridwidth = GridBagConstraints.RELATIVE;
  
  //Pass the OK button and GridBagConstraints 
  //object to layout.
    gridbag.setConstraints(OK, c);
  
  //Make the Cancel button the last one 
  //in its row.
    c.gridwidth = GridBagConstraints.REMAINDER:
  
  //Pass the Cancel button and 
  //GridBagConstraints object to layout.
    gridbag.setConstraints(cancel, c);
  
  //Add the OK and Cancel buttons to 
  //container p2.
    p2.add(OK);
    p2.add(cancel);

Settings Explained

The preceding code example and comments give you an idea of how the settings are used and what they do. This section describes the settings with examples. You can also refer to Using Layout Mangers in The Java Tutorial for additional information on the GridBagConstraints settings and all of the AWT layout managers.

 

gridx and gridy

The gridx and gridy settings indicate at which row (gridx) or column (gridy) the component should be located. The top row is gridx=0, and the left-most column is gridy=0. The value for gridx/gridy can either be an integer corresponding to the explicit row/column or the value GridBagConstraints.RELATIVE, which indicates that the component should be placed in the row/column subsequent to the row/column where the last component was placed.

For example, when adding components to a row, gridx=GridBagConstraints.RELATIVE places the component to the right of the component just added to the row. If a component was just added to Row 2 in Column 1, the next component is added to Row 2 in Column 2.

When adding components to a column, gridy=GridBagConstraints.RELATIVE places the component below the component just added to the column. If a component was just added to Column 0 in Row 1, the next component is added to Column 0 in Row 2.

You can set the value of gridx or gridy to an integer to bypass the default sequential placement. Note that GridBagConstraints.NONE and GridBagConstraints.REMAINDER have no meaning in this context.

If you add the following gridx and gridy settings to the code for the OK and Cancel buttons in the demonstration, the buttons swap positions:

  c.gridx=1;
  c.gridy=3;
  
  c.fill = GridBagConstraints.NONE;
  c.gridwidth = GridBagConstraints.RELATIVE;
  OK = new Button("OK");
  gridbag.setConstraints(OK, c);
  p2.add(OK);
  
  c.gridx=0;
  c.gridy=3;
  cancel = new Button("Cancel");
  gridbag.setConstraints(cancel, c);
  p2.add(cancel);

gridwidth and gridheight

The gridwidth and gridheight settings indicate the number of cells in the display area for a component. The default values are gridwidth=1 and gridheight=1 meaning that by default components are one column wide (gridwidth), and one row high (gridheight).

You can make a component two columns wide with gridwith=2 or three rows high with gridheight=3. Setting gridwidth to GridBagConstraints.REMAINDER indicates the component should take up the remaining number of cells in the row. Setting it to GridBagConstraints.RELATIVE indicates that the component should take up all the remaining sells in the row except the last one.

When you specify a component as the last or next-to-last component in a row, you can give it a gridheight value greater than one so the component spans multiple rows. However, in this case, there is no way to make the component wider than one column when it is the last or next-to-last component in the row.

Due to a GridBagLayout bug, you can use gridheight to have a component span multiple rows only if the component is in Column 0 or if gridx and gridy have positive values.

If you add the following weighty and fill settings to the code for the OK and Cancel buttons in the demonstration, the OK button appears two columns high:

  c.weighty=1.0;
  c.fill = GridBagConstraints.VERTICAL;
  c.gridheight=2;
  c.gridwidth = GridBagConstraints.RELATIVE;
  OK = new Button("OK");
  gridbag.setConstraints(OK, c);
  p2.add(OK);
  
  c.fill=GridBagConstraints.NONE;
  c.gridheight=1;
  cancel = new Button("Cancel");
  gridbag.setConstraints(cancel, c);
  p2.add(cancel);

weightx and weighty

When the user resizes a window using a grid bag layout, the weightx and weighty settings determine how the components resize. By default the settings are weightx=0 and weighty=0, which means that when the window is resized, the components stay grouped together in the center of the container.

If you give weightx a value greater than 0, the components expand in the x direction (horizontally).

If you give weighty a value greater than 0, the components expand in the y direction (vertically).

Test this by resizing the demonstration window with GridBag Layout selected. In the code, c.weightx=1.0 and c.weighty=0.0 so the components resize with the window horizontally, but remain together in the center vertically.

In the gridwidth and gridheight example, the c.weighty value is changed from 0.0 to 1.0 and used with a gridheight value of 2 and a fill value of GridBagConstraints.VERTICAL so the OK button spans two rows, but fills in the vertical direction only.

fill

The fill settings determines how a component fills the display area defined by gridx/gridy/gridwidth/gridheight. The fill can be set to the following values:

GridBagConstraints.HORIZONTAL: The component expands horizontally to fill the entire width of its display area.

GridBagConstraints.VERTICAL: The component expands vertically to fill the entire height of its display area.

GridBagConstraints.BOTH: The component expands to completely fill the entire display area.

GridBagConstraints.NONE: The component is sized to its ideal size regardless of the size of the display area.

In the gridwidth and gridheight example, the c.fill value is changed from GridBagConstraints.BOTH to GridBagConstraints.VERTICAL and used with a weighty value of 1.0 and a gridheight value of 2 so the OK button spans two rows, but fills in the vertical direction only.

If you add the following fill setting to the code for the OK and Cancel buttons in the demonstration, they expand horizontally to fill their display areas. They also fill the entire row because in the demonstration, there are two buttons and two columns in the row. Note that the text area spans its entire row because the fill setting for it is fill=GridBagConstraints=BOTH and there is one component in a two-column row.

c.fill=GridBagConstraints.HORIZONTAL;
c.gridwidth = GridBagConstraints.RELATIVE;
OK = new Button("OK");
gridbag.setConstraints(OK, c);
p2.add(OK);
  
c.gridheight=1;
cancel = new Button("Cancel");
gridbag.setConstraints(cancel, c);
p2.add(cancel);

anchor

When a component is smaller than its display area, you can anchor the component in the following locations within its display area:

anchor=GridBagConstraints.CENTER (the default)
anchor=GridBagConstraints.NORTH
anchor=GridBagConstraints.NORTHEAST
anchor=GridBagConstraints.EAST
anchor=GridBagConstraints.SOUTHEAST
anchor=GridBagConstraints.SOUTH
anchor=GridBagConstraints.SOUTHWEST
anchor=GridBagConstraints.WEST
anchor=GridBagConstraints.NORTHWEST

If you add the following anchor settings to the code for the OK and Cancel buttons, the OK button moves to the west side of its display area and the Cancel button stays in the center:

  
c.fill=GridBagConstraints.NONE;
  c.anchor = GridBagConstraints.WEST;
  c.gridwidth = GridBagConstraints.RELATIVE;
  OK = new Button("OK");
  gridbag.setConstraints(OK, c);
  p2.add(OK);
  
  c.anchor = GridBagConstraints.CENTER;
  c.gridheight=1;
  cancel = new Button("Cancel");
  gridbag.setConstraints(cancel, c);
  p2.add(cancel);

Make sure to use the appropriate fill setting, however, because if the component fills its display area in the wrong direction the anchor setting will have no effect on the component's position.

For example, if you have a component that spans two rows and fills vertically, anchoring the component in the North, Center, or South areas will not change its look. If it is not filling horizontally, however, anchoring it in the northeast, east, southeast, southwest, west, or northwest will change the position.

ipadx and ipady

The layout manager calculates the size of a component based on grid bag constraint settings and the other components in the layout. You can specify an internal padding to increase the calculated size of a component to make the component wider (ipadx) or taller (ipady) than its calculated size, yet not fill the entire display area the way the HORIZONTAL or VERTICAL fill setting does.

By default ipadx and ipady are 0. When you specify an ipadx value, the total component width is its calculated width plus 2 times the padding (the padding is placed on both sides of the component). When you specify an ipady value, the total component height is its calculated height plus 2 times the padding (the padding is placed on the top and bottom of the component).

If you add the following ipadx setting to the code for the OK and Cancel buttons in the demonstration, the buttons are 25 pixels wider on each side:

  c.fill=GridBagConstraints.NONE;
  c.ipadx = 50;
  c.gridwidth = GridBagConstraints.RELATIVE;
  OK = new Button("OK");
  gridbag.setConstraints(OK, c);
  p2.add(OK);
  
  c.gridheight=1;
  cancel = new Button("Cancel");
  gridbag.setConstraints(cancel, c);
  p2.add(cancel);

insets

The insets setting lets you specify the minimum amount of space between the component and the edges of the component's display area. By default, the insets space is left blank, but it could also be used to render a border and/or title.

The insets setting takes a java.awt.Insets object as its value.

If you add the following insets setting to the code for the OK and Cancel buttons, a 15 pixel border is placed between the buttons and the Text Area above.

  
//Specify 15 pixel inset on the top, 0 
//inset on the left, 
  //0 inset on the bottom and 0 inset on the right
    c.insets = new Insets(15, 0, 0, 0);
    c.fill=GridBagConstraints.NONE;
    c.gridwidth = GridBagConstraints.RELATIVE;
    OK = new Button("OK");
    gridbag.setConstraints(OK, c);
    p2.add(OK);
  
    c.gridheight=1;
    cancel = new Button("Cancel");
    gridbag.setConstraints(cancel, c);
    p2.add(cancel);

Conclusion

GridBagLayout is the most powerful and flexible AWT layout manager. Once you become comfortable with the settings and how they can be combined to achieve different visual effects, you can use GridBagLayout to give a very appealing and user-friendly layout to your applictions. However, if layout needs are simple and straightforward, BorderLayout, CardLayout, FlowLayout, or GridLayout can work just as well.

You can view the source code for the demonstration application here. One version uses AWT components and the other uses Swing components. The Swing version compiles and runs with J2SE 1.2 J2SE 1.3. The AWT version compiles with versions 1.1 or later.

Monica Pawlan is a manager and writer at Sun Microsystems, Inc., who enjoys learning and writing about new Java platform technologies. She also likes to garden, play guitar, and travel.