Java Notes

java.awt.GridBagLayout

Description

GridBagLayout lays out components based on a grid with rows and columns that need not all be the same size. If you're familiar with HTML tables, you'll feel comfortable with the idea. Unfortunately, GridBagLayout is infernally awkward and error-prone to use. After reading some of this you might want to see example code at Example: GridBagLayout.

Abandon hope, all ye who use GridBagLayout

Altho GridBagLayout can produce acceptable results, it's not a happy story.

Subpanels for unrelated components. An entire window may require use of nested panels -- don't try to force everything into one giant GridBagLayout. If some groups of components (eg, radio buttons, groups of buttons, checkboxes) are unrelated to alignment with other components, put them in their own panel and use an appropriate layout (often GridLayout).

Unequal rows and columns

The underlying idea is rows and columns, similar to HTML tables.

Three categories of constraint parameters

GridBagLayout performs three functions using values from the GridBagConstraints parameter in the add() method. The names [note the case violations of the standard Java naming convention] are the following.

  1. Grid position, width and height describe the display area.. gridx, gridy, gridwidth, and gridheight.
  2. Position within the display area. fill, anchor, insets, ipadx, and ipady.
  3. Identifying rows and columns which receive extra space on expansion. weightx, and weighty.

Constructor

JPanel p = new JPanel(new GridBagLayout());

or

JPanel p = new JPanel();
p.setLayout(new GridBagLayout());

Do not give the number of rows and columns when you create a new GridBagLayout. The are computed by the layout manager as a consequence of what you add.

Adding a component

Components are added to JPanel p like this:

p.add(component, constraintObj);

Constraint parameters are instance fields in a GridBagConstraints object. The add() method clones (copies) the constraint object, so typically the same GridBagConstraints object is reused to pass constraints for the next component. It is common to use only one GridBagConstraints object to add all components, changing fields as necessary between adds, but this practice also leads to many errors and code which is difficult to change.

GridBagConstraints fields

The fields can divided into three groups:

Necessary - row and column coordinates, width and height in terms of rows and columns
Describe the location and size (in rows and columns) of the component using gridx, gridy, gridwidth, and gridheight.
Common - expandability and alignment
If a column or row can use extra space when a window is expanded, set weightx and weighty to 1.0; you will rarely want to use other values.

Use fill depending on what the type of component is. For example, a JTextField can usually grow horizontally, so you would use

gbc.fill = GridBagConstraints.HORIZONTAL;
to allow it to stretch.

Use anchor to tell which edges of the display area a component should be attached to.

Less common - surrounding spacing
You can also control the space around a component with ipadx and ipady.

To control the amount of unused space around a component, use insets.

GridBagConstraints attribute summary

gridx
gridy
The int column (gridx) and row (gridy) of the component. If requires more than one cell (gridwidth or gridheight > 1), this is the coordinate of the top-left cell. The row and columns start at zero. The value GridBagConstraints.RELATIVE places the component in the next position.
gridwidth
gridheight
Number of columns or rows the component occupies. GridBagConstraints.REMAINDER indicates that this component should fill out all rows or columns to the end. Default 1. Note these names violates naming standards (second word not capitalized).
weightx
weighty
These double variables (default value 0) are used in calculating where space is allocated in rows and columns when a window is resized. extra space should be allocated in a column horizontally (weightx) and row vertically (weighty).

A column width is originally calculated as the maximum width of the preferred sizes of the components in that column. If a component is narrower than the column width, the value of the fill attribute is used in deciding how to use that extra space (see below).

Extra horizontal space is allocated to a column in proportion to the maximum weightx value for that column. If weightx is zero, no extra space is allocated. Because these weights are relative, you can assign any arbitrary positive double value to produce the desired layout, altho it is common to work in the range 0-1. The analogous procedure is performed for the row heights using weighty.

fill Fill specifies how the component should expand within its display area if the area width/height is larger than its preferred size.
   GridBagConstraints.NONE       // Can't expand (Default)
   GridBagConstraints.VERTICAL   // Expand vertically
   GridBagConstraints.HORIZONTAL // Expand horizontally
   GridBagConstraints.BOTH       // Expand vertically and horizontally

For example, a text field typically expands horizontally (GridBagConstraints.HORIZONTAL), a text area expands vertically and horizontally (GridBagConstraints.BOTH), and a button might not expand at all (GridBagConstraints.NONE). If a component isn't expanded to fill the space, the anchor attribute (see below) is used to specify where it goes within that cell. Default value GridBagConstraints.NONE.

anchor If the component doesn't occupy its entire display area, anchor specifies where it should be placed. The location is usually given as a compass direction. (A relative system which works for both right-to-left and left-to-right languages is also available).
   GridBagConstraints.CENTER (the default),
   GridBagConstraints.NORTH     GridBagConstraints.SOUTH
   GridBagConstraints.NORTHEAST GridBagConstraints.SOUTHWEST
   GridBagConstraints.EAST      GridBagConstraints.WEST
   GridBagConstraints.SOUTHEAST GridBagConstraints.NORTHWEST
insets A java.awt.Insets object adds padding space to the component. Insets should be rarely used because they often produce bad results, with the exception of JPanels and JLabels. The constructor parameters (in pixels) specify the top, left, bottom, right. For example,
gbc.insets = new Insets(10, 5, 10, 4);
Default value: Insets(0,0,0,0).
ipadx
ipady
These int fields specify an increase or decrease in the horizontal and/or vertical preferred size of the component. Default value 0. Negative values can be used to tighten the spacing. These values are rarely useful, altho they can be used for fine-tuning spacing.

Java Idiom

It's common to write a utility method which sets the fields of a GridBagConstraints object. For example,

GridBagConstraints gbc = new GridBagConstraints();
. . .
private void set_gbc(int row, int column, int width, int height, int fill) {
   gbc.gridy = row;
   gbc.gridx = column;
   gbc.gridwidth = width;
   gbc.gridheight = height;
   gbc.fill = fill;  // GridBagConstraints.NONE .HORIZONTAL .VERTICAL .BOTH
   // leave other fields (eg, anchor) unchanged.
}
. . .
   set_gbc(3, 2, 2, 1, GridBagConstraints.HORIZONTAL);
   gbc.insets = new Insets(3,3,3,3);  // put spacing around this field.
   p.add(myTextField, gbc);

Adding a component

To add myField to the third row (2) and first column (0), where the button will be one grid cell wide and one high, and it will be able to expand horizontally, do this:

set_gbc(2, 0, 1, 1, GridBagConstraints.HORIZONTAL);
gridbag.setConstraints(myField, gbc);
panel.add(myField);

Opinion

GridBagLayout is not a nice piece of software. The GridBagConstraints object is awkward to use. It allows you to make careless mistakes in the layout without warnings or error messages. There is little good documentation on how the parameters are used. A better version of it would be very welcome.

Consider using a better layout manager. See Alternate Layout Managers.

Some convenience classes for working with GridBaglayout

The difficulties of using GridBagLayout have spawned hundreds of convenience classes for dealing with it. Here are some.