# Java: java.awt.GridBagLayout

## Description

Altho `GridBagLayout` produces the best general results when components must be aligned, it's not a happy story.

- It is very difficult to work with because eleven constraint values are used for each component! These constraint values are bundled in a `java.awt.GridBagConstraints` object.
- Resizing below the preferred size results in an unrecoverable implosion of the layout. Reportedly Sun is rewriting GridBagLayout in Java 6, which will fix some of these bugs.
- The layout doesn't have any features which specifically help to use Sun's (or anyone else's) Human Interface Guidelines.
- Spacing is specified in pixels, which provides no flexibility for screen resolution and font changes.
- Everyone who has touched GridBagLayout will enjoy Totally Gridbag, little bit of Flash foolishness - madbean.com/blog/2004/17/totallygridbag.html

GridBagLayout can do a very good job of layout for individual panels, but windows are often built from several nested panels, each with its own layout manager.

## Unequal rows and columns

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

- Rows and columns don't all have to be same size. The size of each row and column is adjusted depending on maximum component size in the row/column and their constraints.
- A component display area may span several rows and/or columns. Describe this area by giving the row, column, width (in columns), and height (in rows).
- A components doesn't have to fill its display area; constraints describe how to align it within its area.

## 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.

## 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 instance variables - which are important

The fields can divided into three groups:

Necessary
  Describe the location and size (in rows and columns) of the component using `gridx, gridy, gridwidth`, and `gridheight`.
Common
  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
  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

- EZPanel provides a simple interface to GridBagLayout, with automatic generation of borders and gaps, and additional error checking.
- www.horstmann.com/articles/Taming_the_GridBagLayout.html is Cay Horstmann's convenience class for working with GridBagLayout.
- http://manning.com/sbe/files/uts2/Chapter4html/Chapter4.htm has a helper class called GriddedPanel by James Tan. It can be found in the book Absolute Java by Walter Savitch.
- xnap.sourceforge.net/apidocs/org/xnap/gui/util/GridBagHelper.html
- ulc-community.canoo.com/layout/docs/api/com/canoo/ulc/community/layout/application/package-summary.html
- http://www2.sys-con.com/ITSG/virtualcd/Java/archives/0605/dodd/