GridBagLayout

GridBagLayout is an extremely flexible and powerful layout that provides more control than GridLayout in laying out grids. GridBagLayout positions components horizontally and vertically on a rectangular grid, but the components do not have to be the same size and they can fill up more than one cell.

Example

GridBagLayout

For each component in a GridBagLayout container, you use a GridBagConstraints object to have control over,

Using GridBag constraints

There is a one-to-one relationship between each component and constraint object in a GridBagLayout container. Therefore, for GridBagLayout to work correctly, you need a customized GridBagConstraints object for each of the container's components. Using a GridBagConstraints object, you specify the layout information for each component in a GridBagLayout container.

When you manually create the code for a GridBagLayout container, you really only need to create one GridBagConstraints object for each GridBagLayout container. GridBagLayout uses the GridBagConstraints default values, or reuses the most recently specified values for each component you add to the container.

However, when you design a GridBagLayout container in JBuilder's UI Designer, the UI Designer always creates a new GridBagConstraints2 object for each component you add, and you set the values for these constraints in each component's constraints property in the Inspector.

GridBagConstraints2 derives from GridBagConstraints. In addition, GridBagConstraints2 has a constructor that takes all eleven properties of GridBagConstraints so the code generated by the UI Designer can be simpler.

For example,

    bevelPanel1.add(buttonControl1, new GridBagConstraints2(8, 1, 2, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 14, 0, 0), 0, 0));
    bevelPanel1.add(textFieldControl1, new GridBagConstraints2(0, 1, 4, 1, 1.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 24, 0, 0), 129, 0));
    bevelPanel1.add(textFieldControl2, new GridBagConstraints2(0, 3, 5, 1, 1.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 24, 0, 0), 136, -4));
    bevelPanel1.add(textFieldControl3, new GridBagConstraints2(0, 5, 6, 2, 1.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 24, 0, 0), 150, 0));
    bevelPanel1.add(textFieldControl4, new GridBagConstraints2(0, 8, 7, 1, 1.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 24, 0, 0), 156, 2));
    bevelPanel1.add(labelControl1, new GridBagConstraints2(0, 0, 2, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(11, 24, 0, 0), 18, -7));
    bevelPanel1.add(labelControl2, new GridBagConstraints2(0, 2, 4, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(18, 24, 0, 0), 50, -4));
    bevelPanel1.add(labelControl3, new GridBagConstraints2(0, 4, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(9, 24, 0, 0), -21, -5));
    bevelPanel1.add(labelControl4, new GridBagConstraints2(0, 7, 2, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 24, 0, 0), 26, -3));
    bevelPanel1.add(checkboxControl1, new GridBagConstraints2(7, 5, 4, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(8, 29, 0, 24), 18, -11));
    bevelPanel1.add(buttonControl2, new GridBagConstraints2(7, 8, 4, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 27, 0, 24), 65, 5));
    bevelPanel1.add(buttonControl3, new GridBagConstraints2(0, 9, 3, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(50, 69, 11, 0), 0, 0));
    bevelPanel1.add(buttonControl4, new GridBagConstraints2(3, 9, 5, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(51, 9, 11, 0), 0, 0));
    bevelPanel1.add(buttonControl5, new GridBagConstraints2(8, 9, 1, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(51, 7, 11, 0), 0, 0));
  }
}

GridBagLayout determines the container's preferredSize and where to place the components based not only on the GridBagConstraints, but also on each component's minimumSize.

GridBagLayout is a complicated layout manager that requires some study and practice to understand it. To learn the behavior of all the constraints, start with some sample code (provided by JBuilder), and practice adding and modifying constraints and components until you begin to understand how the constraints work and how they affect each other.

For more information on GridBagLayout and GridBagConstraints, read GridBagLayout and GridBagConstraints in the JDK documentation. Also look at and experiment with various examples you can find on the Web.

GridBagConstraints: definitions and values

The following section lists all the GridBagConstraints with their valid and default values. In Java there are numeric values that correspond to text values. However, since JBuilder displays only the text values in the Inspector, we have not listed their numeric equivalents here unless they are appropriate for JBuilder.

You can set a component's GridBagConstraints manually in the code, or you can use the Inspector to select values for each component from its constraints property.

To use the Inspector for setting GridBagConstraints,

  1. Select the GridBagLayout container in the UI Designer.
  2. In the Component Tree or in the UI Designer, select the component you want to modify.
  3. In the Inspector, select the constraints property and click the ellipsis button to display the Constraints property editor.
  4. Set the desired constraints in the property editor, then press OK.
For information on how these constraints work, see the topic on each of the constraints which follow.
anchor
When the component is smaller than its display area, use the anchor constraint to tell the layout manager where to place the component within the area.

The anchor constraint only affects the component within its own display area, depending on the fill constraint for the component. For example, if the fill constraint value for a component is GridBagConstraints.BOTH (fill the display area both horizontally and vertically), the anchor constraint has no effect because the component takes up the entire available area. For the anchor constraint to have an effect, set the fill constraint value to GridBagConstraints.NONE, GridBagConstraints.HORIZONTAL, or GridBagConstraints.VERTICAL

Valid values:
   
GridBagConstraints.CENTER
GridBagConstraints.NORTH
GridBagConstraints.NORTHEAST
GridBagConstraints.EAST
GridBagConstraints.SOUTHEAST
GridBagConstraints.SOUTH
GridBagConstraints.SOUTHWEST
GridBagConstraints.WEST
GridBagConstraints.NORTHWEST
Default value:
   
GridBagConstraints.CENTER

fill
When the component's display area is larger than the component's requested size, use the fill constraint to tell the layout manager if the component needs to be resized, and if so, how.

As with the anchor constraint, the fill constraint only affects the component within its own display area. Fill tells the layout manager to expand the component to fill the whole area it has been given.

Valid values:
   
GridBagConstraints.NONE (Don't change the size of the component.)
   
GridBagConstraints.BOTH (Resize the component both horizontally and vertically to fill the area completely.)
   
GridBagConstraints.HORIZONTAL (Only resize the component to fill the area horizontally.)
   
GridBagConstraints.VERTICAL (Only resize the component to fill the area vertically.)
Default value:
   
GridBagConstraints.NONE

gridwidth, gridheight
Use these constraints to specify the number of cells in a row (gridwidth) or column (gridheight) the component uses. This constraint value is stated in cell numbers, not in pixels.

Valid values:
   
gridwidth=nn, gridheight=nn
 
(Where nn is an integer representing the number of cell columns or rows.)
   
GridBagConstraints.RELATIVE (-1)
 
Specifies that this component is the next to last one in the row (gridwidth) or column (gridheight.) A component with a GridBagConstraints.RELATIVE takes all the remaining cells except the last one. For example, in a row of six columns, if the component starts in the third column, a gridwidth of RELATIVE will make it take up columns three, four, and five.
   
GridBagConstraints.REMAINDER (0)
 
Specifies that this component is the last one in the row (gridwidth) or column (gridheight).
Default value:
   
gridwidth=1, gridheight=1

gridx, gridy
Use these constraints to specify the grid cell location for the upper left corner of component. For example, gridx=0 is the first column on the left, and gridy=0 is the first row at the top. Therefore, a component with the constraints gridx=0 and gridy=0 is placed in the first cell of the grid (top left).

GridBagConstraints.RELATIVE (the default value) specifies that the component be placed relative to the previous component as follows:

Valid values:
   
gridx=nn, gridy=nn
GridBagConstraints.RELATIVE (-1)
Default value:
   
gridx=1, gridy=1

insets
Use insets to specify the minimum amount of external space (padding) in pixels between the component and the edges of its display area.

Valid values:
insets = new Insets(n,n,n,n)
Top, left, bottom, right (where each parameter represents the number of pixels between the display area and one edge of the component.)
Default values:
insets = new Insets(0,0,0,0)

ipadx, ipady
These constraints specify the internal padding for a component. Use ipadx and ipady to specify the amount of space (in pixels) to add to the minimum size of the component for internal padding. For example, the width of the component will be at least its minimum width plus ipadx in pixels (in spite of the fact that the Javadoc comments say ipadx*2, the actual code only adds it once). Similarly, the height of the component will be at least the minimum height plus ipady pixels.

Example:

When added to a component that is 30 pixels wide and 20 pixels high:

Valid values:
   
ipadx=nn, ipadx=nn
Default value:
   
ipadx=0, ipady=0

weightx, weighty
Use the weight constraints to specify how to distribute the extra space vertically (weightx) and horizontally (weighty) when the container is resized. Weights determine what share of extra space each component gets when the container is enlarged beyond its default size.

If a component has weight, but no fill, then the extra space goes to the padding around the component instead of making the component larger.

For example, if you have three components with weights of 0.0, 0.3, and 0.2, when the container is enlarged, none of the extra space will go to the first component, 3/5 of it will go the second component, and 2/5 of it will go to the third.

If all the components have weights of zero in a single direction, the components will clump together in the center of the container for that dimension and won't expand beyond their preferred size. GridBagLayout puts any extra space between its grid of cells and the edges of the container.

Weight values are of type double and are specified numerically in the range 0.0 to 1.0 inclusive. Zero means the component should not receive any of the extra space, and 1.0 means component gets a full share of the space.

Valid values:
   
weightx=n.n, weighty=n.n
Default value:
   
weightx=0.0, weighty=0.0

Sample GridBagLayout source code

The code sample used below is taken from the JBuilder Connection Descriptor property editor for the Database component. This UI uses one GridBagLayout panel for all the components except the OK, Cancel, and Help buttons. These buttons are part of the surrounding dialog container.

To see this editor live, drop a Database component onto the Component Tree, select the connection property and click the ellipsis button .

GridBagLayout property editor

The source code shown is the section of the file that deals with GridBagLayout.

    GridBagLayout gridBagLayout = new GridBagLayout();
    setLayout(gridBagLayout);

    GridBagConstraints gridBagConstraints = new GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;

    // Set some nonzero weight factors to allow components to reposition
    // when the panel is resized, otherwise they stay clustered in the center.
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.weighty = 1.0;

    Label labelURL = new Label(Res.getString(Res.CONNECTIONURL));
    labelURL.setAlignment(0);
    add(labelURL);
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
    gridBagConstraints.anchor = GridBagConstraints.SOUTHWEST;       // anchor close to URL field below and left align
    gridBagLayout.setConstraints(labelURL, gridBagConstraints);

    connectionURLField = new TextField("", 24);
    add(connectionURLField);
    gridBagConstraints.gridy = 1;
    gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;    // make URL field take whole row
    gridBagConstraints.anchor = GridBagConstraints.WEST;            // left align field
    //gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;  //$$$
    gridBagLayout.setConstraints(connectionURLField, gridBagConstraints);

    gridBagConstraints.fill = GridBagConstraints.NONE;              // undo the custom settings from above

    browseUrlsButton = new Button(Res.getString(Res.BROWSE_URLS));
    add(browseUrlsButton);
    gridBagConstraints.gridx = 3;
    gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
    gridBagConstraints.anchor = GridBagConstraints.EAST;
    gridBagLayout.setConstraints(browseUrlsButton, gridBagConstraints);

    Label labelUser = new Label(Res.getString(Res.USERNAME));
    labelUser.setAlignment(0);
    add(labelUser);
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.anchor = GridBagConstraints.SOUTHWEST;       // anchor close to field below and left align
    gridBagConstraints.gridwidth = 1;
    gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
    gridBagLayout.setConstraints(labelUser, gridBagConstraints);

    userNameField = new TextField("", 12);
    add(userNameField);
    gridBagConstraints.gridx = GridBagConstraints.RELATIVE;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.gridwidth = 1;
    gridBagConstraints.anchor = GridBagConstraints.WEST;
    gridBagLayout.setConstraints(userNameField, gridBagConstraints);

    Label labelPassword = new Label(Res.getString(Res.PASSWORD));
    labelPassword.setAlignment(0);
    add(labelPassword);
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 4;
    gridBagConstraints.anchor = GridBagConstraints.SOUTHWEST;
    gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
    gridBagLayout.setConstraints(labelPassword, gridBagConstraints);

    passwordField = new TextField("", 12);
    add(passwordField);
    gridBagConstraints.gridy = 5;
    gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
    gridBagConstraints.anchor = GridBagConstraints.WEST;
    gridBagLayout.setConstraints(passwordField, gridBagConstraints);

    passwordField.setEchoChar('*');                                     // password field shows "****" only

    promptCheckBox = new Checkbox(Res.getString(Res.USERPROMPT));
    add(promptCheckBox);
    gridBagConstraints.gridx = 3;
    gridBagConstraints.anchor = GridBagConstraints.EAST;
    gridBagLayout.setConstraints(promptCheckBox, gridBagConstraints);

    Label labelDriver = new Label(Res.getString(Res.DRIVER));
    labelDriver.setAlignment(0);
    add(labelDriver);
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 7;
    gridBagConstraints.anchor = GridBagConstraints.SOUTHWEST;
    gridBagConstraints.gridwidth = 1;
    gridBagLayout.setConstraints(labelDriver, gridBagConstraints);

    driverField = new TextField("", 22);
    add(driverField);
    gridBagConstraints.gridy = 8;
    gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
    gridBagConstraints.anchor = GridBagConstraints.WEST;
    gridBagLayout.setConstraints(driverField, gridBagConstraints);

    testButton = new Button(Res.getString(Res.TESTCONNECT));
    add(testButton);
    gridBagConstraints.gridx = 2;
    gridBagConstraints.gridy = 8;
    gridBagConstraints.anchor = GridBagConstraints.EAST;
    gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
    gridBagLayout.setConstraints(testButton, gridBagConstraints);

    statusArea = new TextArea(3, 40);     // ask for just 3 rows to keep status area relatively short
    add(statusArea);
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 9;
    gridBagConstraints.anchor = GridBagConstraints.SOUTHWEST;
    gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
    gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
    gridBagConstraints.gridheight = GridBagConstraints.REMAINDER;
    gridBagConstraints.insets = new Insets(10,0,10,0);                  // introduce some white space above and below
    gridBagLayout.setConstraints(statusArea, gridBagConstraints);