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

- 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. Fortunately, most of them have reasonable defaults.
- The layout doesn't have features which specifically help to use Sun's (or anyone else's) Human Interface Guidelines, for example in handling gaps.
- Spacing is specified in pixels, which provides no flexibility for screen resolution and font changes.
- I like this quote from Otaku, Cedric's blog: "GridBagLayout is an absolute disaster and the perfect example of something that is completely flawed and violates with a stunning regularity the principle of least surprise."
- Everyone who has touched GridBagLayout will enjoy Totally Gridbag, little bit of Flash foolishness - madbean.com/blog/2004/17/totallygridbag.html
- Some prefer to call it "GridBugLayout".

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.

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

- www.horstmann.com/articles/Taming_the_GridBagLayout.html is Cay Horstmann's convenience class for working with GridBagLayout.
- Evan Summer's Swing and Roundabouts 4: Grid Bag Grease (weblogs.java.net/blog/evanx/archive/2006/07/swing_and_round_1.html)
- Packer at https://packer.dev.java.net/.
- The book Absolute Java by Walter Savitch has a helper class called GriddedPanel by James Tan.
- 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