GridBagLayout

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

Example

GridBagLayout

GridBagLayout determines the placement of its components based on each component's constraints and minimum size, plus the container's preferred size.

In the following discussion,

While GridBagLayout can accommodate a complex grid, it will behave more successfully (and more predictably) if you organize your components into smaller panels, nested inside the GridBagLayout container. These nested panels can use other layouts, and can contain additional panels of components if necessary. This method has two advantages:

About GridBagConstraints

GridBagLayout uses a GridBagConstraints object to specify the layout information for each component in a GridBagLayout container. Since there is a one-to-one relationship between each component and GridBagConstraints object, you need to customize the GridBagConstraints object for each of the container's components.

GridBagLayout components have the following constraints:

GridBagConstraints give you control over,

For a detailed explanation of each of the constraints, including tips for using them and setting them in the UI Designer, see the individual constraint topics below.

Setting GridBagConstraints manually in the source code

When you use the UI Designer to design a GridBagLayout container, JBuilder always creates a new GridBagConstraints2 object for each component you add to the container. GridBagConstraints2 is derived from GridBagConstraints, and 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(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(checkboxControl1, new GridBagConstraints2(7, 5, 4, 1, 0.0, 0.0,
                               GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(8, 29, 0, 24), 18, -11));
 

You can modify the parameters of the GridBagConstraints2 constructor directly in the source code, or you can use the Constraints property editor to change the values.

When you create a GridBagLayout container by coding it manually, you really only need to create one GridBagConstraints object for each GridBagLayout container. GridBagLayout uses the GridBagConstraints default values for the component you add to the container, or it reuses the most recently modified value. If you want the component you're adding to the container to have a different value for a particular constraint, then you only need to specify the new constraint value for that component. This new value will stay in effect for subsequent components unless, or until, you change it again.

Note: While this method of coding GridBagLayout is the leanest (recycling constraint values from previously added components), it doesn't allow you to edit that container visually in JBuilder's UI Designer.

Modifying existing GridBagLayout code to work in the UI Designer

If you have a GridBagLayout container that was previously coded manually by using one GridBagConstraints object for the container, you will not be able to edit that container in the UI Designer without making the following modifications to the code:

Designing GridBagLayout visually in the UI Designer

GridBagLayout is a complex layout manager that requires some study and practice to understand it, but once it is mastered, it is extremely useful. JBuilder has added some special features to the visual design tools that make GridBagLayout much easier to design and control, such as a Constraints property editor, a grid, drag and drop editing, and a pop-up menu on selected components.

There are two approaches you can take to designing GridBagLayout in the UI Designer. You can design it from scratch by adding components to a GridBagLayout panel, or you can prototype the panel in the UI Designer using another layout first, such as XYLayout, then convert it to GridBagLayout when you have all the components arranged and sized the way you want. This method can speed up your design work substantially.

Whichever method you use, it is recommended that you take advantage of using nested panels to group the components, building them from the inside out. Use these panels to define the major areas of the GridBagLayout container. This will greatly simplify your GridBagLayout design giving you fewer cells in the grid and fewer components that need GridBagConstraints.

Converting to GridBagLayout

When you prototype your layout in another layout first, such as XYLayout, the conversion to GridBagLayout will be much cleaner and easier if you are careful about the alignment of the panels and components as you initially place them, especially left and top alignment. Keep in mind that you are actually designing a grid, so try to place the components inside an imaginary grid, and use nested panels to keep the number of rows and columns as small as possible. Using XYLayout for prototyping gives you the advantage of component alignment functions on the components' pop-up menu (accessed by right-clicking a component in the UI Designer).

As the UI Designer converts the design to GridBagLayout, it assigns constraint values for the components based on where the components were before you changed the container to GridBagLayout. Often, only minor adjustments are necessary, if any.

Converting to GridBagLayout assigns weight constraints to certain types of components (those which you would normally expect to increase in size as the container is enlarged at runtime, such as text areas, fields, group boxes, or lists). If you need to make adjustments to your design after converting to GridBagLayout, you'll find the task much easier if you remove all the weight constraints from any components first (set them all to zero).

If even one component has a weight constraint value greater than zero, it is hard to predict the sizing behavior in the UI Designer due to the complex interactions between all the components in the container.

You can easily spot a GridBagLayout whose components have weights because the components will not be clustered together in the center of the container. Instead, the components fill the container to its edges.

Tip: When you remove all the weights from the components in a GridBagLayout, one of two things will happen:

See the topic below on weight constraints for more details on how to use weights and how they cause components to interact with each other.

Adding components to a GridBagLayout container

If you want to create your GridBagLayout by start out with a new GridBagLayout container and adding all the components to it from scratch, there are certain behaviors you should expect.

Setting GridBagConstraints in the Constraints property editor
All the GridBagConstraints can be specified in the UI Designer without having to edit the source code. This is possible with the GridBagLayout Constraints property editor.

One big advantage to using the Constraints property editor for setting constraints is the ability to change constraints for multiple components at the same time. For example, if you want all the buttons in your GridBagLayout container to use the same internal padding, you can hold down the Shift key while you select each one, then open the Constraints property editor and edit the constraint.

To use the Constraints property editor,

  1. Select the component(s) within the GridBagLayout container you want to modify, either in the Component Tree or in the UI Designer.
  2. Do one of the following to open the Constraints property editor:
  3. Set the desired constraints in the property editor, then press OK.

Note: If you need assistance when using the Constraints property editor, press the Help button or F1.

Displaying the grid
The UI Designer displays an optional grid that lets you see exactly what is happening with each cell and component in the layout.

Using the mouse to change constraints

The UI Designer allows you to use the mouse for setting some of the constraints by dragging the whole component or by grabbing various sizing nibs on the component. Directions for setting constraints visually are included in the individual constraint topics below.

Using the GridBagLayout pop-up menu
Right-clicking a GridBagLayout component displays a pop-up menu that gives you instant access to the Constraints property editor, and lets you quickly set or remove certain constraints.

Menu CommandAction
Show Grid Displays the GridBagLayout grid in the UI Designer.
Remove Padding Sets any size padding values (ipadx and ipady) for the selected component to zero.
Constraints... Displays the Constraints property editor for the selected GridBagLayout component.
Fill Horizontal Sets (ors) the fill constraint value for the component to HORIZONTAL. The component expands to fill the cell horizontally. If the fill was VERTICAL, it sets the constraint to BOTH.
Fill Vertical Sets (ors) the fill constraint value for the component to VERTICAL. The component expands to fill the cell vertically. If the fill was HORIZONTAL, it sets the constraint to BOTH.
Remove Fill Changes the fill constraint value for the component to NONE.
Weight Horizontal Sets the weightx constraint value for the component to 1.0.
Weight Vertical Sets the weighty constraint value for the component to 1.0
Remove Weights Sets both weighty and weighty constraint values for the component to 0.0.

GridBagConstraints

The following section lists each of the GridBagConstraints separately. It defines each one, explaining its valid and default values, and tells you how to set that constraint visually in the UI Designer.

anchor

Description:

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

Setting the anchor constraint in the UI Designer

You can use the mouse to set the anchor for a component that is smaller than its cell. You simply click on the component and drag it, dragging the component toward the desired location at the edge of its display area, much like you would dock a movable toolbar. For example, to anchor a button to the upper left corner of the cell, click the mouse in the middle of the button, and drag it until the upper left corner of the button touches the upper left corner of the cell. This sets the anchor constraint value to NW.

You can also specify the anchor constraint in the Constraints property editor.

  1. Select the component in the UI Designer.
  2. Right-click the component in the UI Designer and choose Constraints to open the Constraints property editor.
  3. Select the desired anchor constraint value in the Anchor area, then press OK.

fill

Description:

When the component's display area is larger than the component's requested size, use the fill constraint to tell the layout manager which parts of the display area should be given to the component.

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

Specifying the fill constraint in the UI Designer

The fastest way to specify the fill constraint for a component is to use the component's pop-up menu in the UI Designer.

  1. Right-click the component in the UI Designer to display the pop-up menu.
  2. Do one of the following:
    • Select Fill Horizontal to set the value to HORIZONTAL
    • Select Fill Vertical to set the value to VERTICAL.
    • Select both Fill Horizontal and Fill Vertical to set the value to BOTH.
    • Select Remove Fill to set the value to NONE.

You can also specify the fill constraint in the Constraints property editor.

  1. Right-click the component in the UI Designer and choose Constraints to display the Constraints property editor.
  2. Select the desired fill constraint value in the Fill area, then press OK.

gridwidth, gridheight

Description:

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

Specifying gridwidth and gridheight constraints in the UI Designer

You can specify gridwidth and gridheight constraint values in the Constraints property editor.

  1. Right-click the component in the UI Designer and choose Constraints to display the Constraints property editor.
  2. In the Grid Position area, enter a value for gridwidth in the Width field , or a value for gridheight in the Height field. Specify the number of cells the component will occupy in the row or column.
    • If you want the value to be RELATIVE, enter a -1.
    • If you want the value to be REMAINDER, enter a 0.
You can use the mouse to change the gridwidth or gridheight by sizing the component into adjacent empty cells.

gridx, gridy

Description:

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 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
Specifying the grid cell location in the UI Designer

You can use the mouse to specify which cell the upper left corner of the component will occupy. Simply click near the upper left corner of the component and drag it into a new cell. When moving components that take up more than one cell, be sure to click in the upper left cell when you grab the component, or undesired side effects can occur. Sometimes, due to existing values of other constraints for the component, moving the component to a new cell with the mouse may cause changes in other constraint values, for example, the number of cells that the component occupies might change.

To more precisely specify the gridx and gridy constraint values without accidently changing other constraints, use the Constraints property editor.

  1. Right-click the component in the UI Designer and choose Constraints to display the Constraints property editor.
  2. In the Grid Position area, enter the column number for gridx value in the X field , or the row number for gridy value in the Y field. If you want the value to be RELATIVE, enter a -1.

Important: When you use the mouse to move a component to an occupied cell, the UI Designer ensures that two components never overlap by inserting a new row and column of cells so the components will not be on top of each other. When you relocate the component using the Constraints property editor, the designer does not check to make sure the components don't overlap.

insets

Description:

Use insets to specify the minimum amount of external space (padding) in pixels between the component and the edges of its display area. The inset says that there must always be the specified gap between the edge of the component and the corresponding edge of the cell. Therefore, insets work like brakes on the component to keep it away from the edges of the cell. For example, if you increase the width of a component with left and right insets to be wider than its cell, the cell will expand to accommodate the component plus its insets. Because of this, fill and padding constraints never steal any space from insets.

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 cell.)
Default values:
insets = new Insets(0,0,0,0)
Setting inset values in the UI Designer

The UI Designer displays blue sizing nibs on a selected GridBagLayout component to indicate the location and size of its insets. Grab a blue nib with the mouse and drag it to increase or decrease the size of the inset.

For more precise control over the inset values, use the Constraints property editor to specify the exact number of pixels.

  1. Right-click the component in the UI Designer and choose Constraints to display the Constraints property editor.
  2. In the External Insets area, specify the number of pixels for each inset: top, left, bottom, or right.
Note that while negative inset values are legal, they can cause components to overlap adjacent components, and are not recommended.

ipadx, ipady

Description:

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. The code only adds it once, splitting it evenly between both sides of the component. Similarly, the height of the component will be at least the minimum height plus ipady pixels.

Example:

When added to a component that has a preferred size of 30 pixels wide and 20 pixels high:

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

Setting the size of internal padding constraints in the UI Designer

You can specify the size of a component's internal padding by clicking on any of the black sizing nibs at the edges of the component, and dragging with the mouse.

For more precise control over the padding values, use the Constraints property editor to specify the exact number of pixels to use for the value.

  1. Right-click the component in the UI Designer and choose Constraints to display the Constraints property editor.
  2. In the Size Padding area, specify the number of pixels for the Width and Height values.
To quickly remove the padding (set it to zero), right-click the component in the UI Designer and choose Remove Padding. You can also select multiple components and use the same procedure to remove the padding from all of them at once.

Note: Negative values will make the component smaller than its preferred size and are perfectly valid.

weightx, weighty

Description:

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

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

Setting weightx and weighty constraints in the UI Designer

To specify the weight constraints for a component in the UI Designer, right-click the component and choose Weight Horizontal (weightx), or Weight Vertical (weighty). This sets the value to 1.0. To remove the weights (set them to zero), right-click the component and choose Remove Weights. You can do this for multiple components: hold down the Shift key when selecting the components, then right-click and choose the appropriate menu item.

If you want to set the weight constraints to something other than 0.0 or 1.0, you can set the values in the Constraints property editor.

  1. Right-click the component(s) and choose Constraints to display the Constraints property editor.
  2. Enter a value between 0.0 and 1.0 for the X (weightx) or Y (weighty) value in the Weight area, then press OK.

Important: Because weight constraints can make the sizing behavior in the UI Designer difficult to predict, setting these constraints should be the last step in designing a GridBagLayout.

Examples of how weight constraints affect components' behavior:

Sample GridBagLayout source code

The code sample used below is taken from the JBuilder Sort property editor for the QueryDataSet component. This UI uses one GridBagLayout panel for all the components.

To see this editor live, drop a QueryDataSet component onto the Component Tree. In the Inspector, select its sort property and click the ellipsis button .

GridBagLayout property editor

Notice that, except for the three buttons on the bottom, the rest of the components fit nicely into a grid of two columns. Since GridBagLayout is based on a grid, it seems to do well with symmetry and does not handle exceptions like these three buttons well. If you try to keep the three buttons in their own individual cells, you would have to add a third column to the design, which means the components above would have to be evenly split across three columns. You could probably have a total of six columns, and come up with a workable solution, but the buttons wouldn't stay the same size when the container is resized at runtime.

There are two other ways you could handle this situation.

Either way, the resizing behavior of the buttons should be satisfactory.

Below is the complete source code for this example.

package untitled3;

import java.awt.*;
import java.awt.event.*;
import borland.jbcl.control.*;
import borland.jbcl.layout.*;
import jclass.bwt.*;
import borland.jbcl.dataset.*;

public class Frame1 extends DecoratedFrame {
  BorderLayout borderLayout1 = new BorderLayout();
  BevelPanel bevelPanel1 = new BevelPanel();
  QueryDataSet queryDataSet1 = new QueryDataSet();
  ListControl listControl1 = new ListControl();
  ListControl listControl2 = new ListControl();
  LabelControl labelControl1 = new LabelControl();
  LabelControl labelControl2 = new LabelControl();
  ButtonControl buttonControl1 = new ButtonControl();
  ButtonControl buttonControl2 = new ButtonControl();
  Checkbox checkbox1 = new Checkbox();
  Checkbox checkbox2 = new Checkbox();
  Button button1 = new Button();
  Button button2 = new Button();
  Button button3 = new Button();
  Panel panel1 = new Panel();
  GridLayout gridLayout1 = new GridLayout();
  GridBagLayout gridBagLayout1 = new GridBagLayout();

  //Construct the frame
  public Frame1() {
    try {
      jbInit();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  //Component initialization
  private void jbInit() throws Exception{
    this.setLayout(borderLayout1);
    this.setSize(new Dimension(323, 285));
    this.setTitle("Frame Title");
    labelControl1.setText("Sorted columns");
    labelControl2.setText("Available columns");
    buttonControl1.setLabel("Remove from Sort");
    buttonControl2.setLabel("Add to Sort");
    checkbox1.setLabel("Descending");
    checkbox2.setLabel("Case insensitive");
    button1.setLabel("OK");
    button2.setLabel("Cancel");
    button3.setLabel("Help");
    gridLayout1.setHgap(6);
    gridLayout1.setColumns(3);
    panel1.setLayout(gridLayout1);
    bevelPanel1.setLayout(gridBagLayout1);
    this.add(bevelPanel1, BorderLayout.CENTER);
    bevelPanel1.add(listControl1, new GridBagConstraints2(0, 1, 1, 1, 1.0, 0.0
            ,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 13, 0, 0), 33, 16));
    bevelPanel1.add(listControl2, new GridBagConstraints2(1, 1, 1, 1, 1.0, 0.0
            ,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 8, 0, 4), 20, 16));
    bevelPanel1.add(labelControl1, new GridBagConstraints2(0, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(3, 13, 0, 0), 38, 0));
    bevelPanel1.add(labelControl2, new GridBagConstraints2(1, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(3, 0, 0, 0), 40, 0));
    bevelPanel1.add(buttonControl1, new GridBagConstraints2(0, 2, 1, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(11, 0, 0, 0), 6, 0));
    bevelPanel1.add(buttonControl2, new GridBagConstraints2(1, 2, 1, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(11, 0, 0, 0), 48, 1));
    bevelPanel1.add(checkbox1, new GridBagConstraints2(0, 3, 1, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(11, 30, 0, 0), 0, 0));
    bevelPanel1.add(checkbox2, new GridBagConstraints2(1, 3, 1, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(11, 7, 0, 0), 0, 0));
    bevelPanel1.add(panel1, new GridBagConstraints2(0, 4, 2, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(6, 0, 6, 0), 0, 0));
    panel1.add(button1, null);
    panel1.add(button2, null);
    panel1.add(button3, null);
  }

  }


For additional information on GridBagLayout and GridBagConstraints, read GridBagLayout and GridBagConstraints in the JDK documentation.