GridBag Layout Manager

The purpose of this document is to: This document also includes the following three sample programs:
  • GridBag1.java - Illustrates the impact of the various constraints on the appearance of the components.
  • GridBag2.java - Illustrates the addition of a series of buttons by specifying their x- and y-coordinates.
  • GridBag3.java - Illustrates the addition of a series of buttons by using the "relative" approach to positioning.


Features of the GridBagLayout

This layout manager is one of the most flexible and also the most complicated of the layout managers. It enables you to place components in rows and columns just like the GridLayout; however, it provides the following additional functionality:
  • Components may be assigned to their cells either by specifying x and y coordinates or through relative positioning.
  • Components may span mutliple rows and/or columns.
  • Components may expand to fill their assigned cell or retain their preferred size.
  • Components may be weighted and additional space within rows and columns assigned to those components with higher weights.
  • If a component does not expand to fill its entire cell, then it may be positioned at any of the "compass" points within the cell or in the center.
  • Internal padding may be defined for a component in order to increase is preferred size.
  • External padding may be defined in order to provide additional separation between components.


How to Use the GridBagLayout

In order to use the GridBagLayout manager, you need to take the following steps:
  1. Create a GridBagLayout object.
  2. Create a GridBagContraints object.
  3. Set the layout for the current container to GridBagLayout.
  4. For each component, change the attributes of the constraints object as necessary.
  5. Associate the current constraint settings with the component.
  6. Add the component to the container.

Here is some sample code:

      GridBagLayout gridbag = new GridBagLayout();
      GridBagConstraints c  = new GridBagConstraints();
      setLayout(gridbag);

      c.fill = GridBagConstraints.BOTH;
      c.weightx = 1.;

      Button button = new Button("OK");
      gridbag.setConstraints(button, c);
      add(button);

GridBagConstraints

The following table provides a comprehensive list of the constraint instance variables along with the default values and a description:

Variable Default Description
gridx -1 The x-coordinate position of the cell starting with 0. The default value of -1 indicates to use relative positioning.
gridy -1 The y-coordinate position of the cell starting with 0. The default value of -1 indicates to use relative positioning.
gridwidth 1 The width of the component measured in cells. It must be non-negative. If the gridwidth is REMAINDER (or 0), the component will occupy all the cells to the right of it. If the gridwidth is RELATIVE, the component will occupy all the cells to its right except for the last cell. Also, the gridwidth of the following component must be REMAINDER.
gridheight 1 The height of the component measured in cells. It must be non-negative. If the gridheight is REMAINDER (or 0), the component will occupy all the cells below it. If the gridheight is RELATIVE, the component will occupy all the cells below it except for the last cell. Also, the gridheight of the following component must be REMAINDER.
ipadx 0 Internal padding for the components width. This field increases the minimum and preferred width of a component by ipadx pixels.
ipady 0 Internal padding for the components height. This field increases the minimum and preferred height of a component by ipady pixels.
insets Insets(0, 0, 0, 0) External padding of the component; i.e., the minimum amount of space between the component and the edges of its display area.
fill GridBagConstraints.NONE Applies when the component's display area is larger than required to hold the component. It is used to determine how to resize the component.
"GridBagConstraints.NONE" indicates that the component will not be resized.
"GridBagConstraints.HORIZONTAL" indicates that it will be resized horizontally but not vertically.
"GridBagConstraints.VERTICAL" indicates that it will be resized vertically but not horizontally.
"GridBagConstraints.BOTH" indicates that it will be resized in both directions.
anchor GridBagConstraints.CENTER Applies when the component's display area is larger than required to hold the component. It is used to indicate where to place the component in the display area. The default, "GridBagConstraints.CENTER", centers the component. The other valid values follow the points of the compass: GridBagConstraints.NORTH, GridBagConstraints.NORTHEAST, GridBagConstraints.EAST,
GridBagConstraints.SOUTHEAST, GridBagConstraints.SOUTH, GridBagConstraints.SOUTHWEST, GridBagConstraints.WEST, GridBagConstraints.NORTHWEST.
weightx 0 Weight used to determine how extra horizontal space is allocated to this component. The absolute value of the weightx is not significant; only how it compares to the weightx's for the other components. If all weightx's are zero, then the cells clump together in the middle and the extra space is put on the edges.
weighty 0 Weight used to determine how extra vertical space is allocated to this component. The absolute value of the weighty is not significant; only how it compares to the weighty's for the other components. If all weighty's are zero, then the cells clump together in the middle and the extra space is put on the edges.


Positioning Components

There are two different approaches which may be used to position components within the grid. One approach is to specify the "gridx" and "gridy" components for each cell as it is added to its container. It is not necessary to add the cells in any particular order and it is possible to leave "holes" in the grid. See the sample program "GridBag2.java".

The other approach is to leave "gridx" and "gridy" at their default values of -1 and then to use the "gridheight" and "gridwidth" to position the components. Under this approach, the order in which components are added is very important. They should be added from left to right and top to bottom. By default "gridwidth" and "gridheight" are 1. If the gridheight is set to REMAINDER, then the current component will be the last one in its column. If the gridwith is set to REMAINDER, then the current component will be the last one in its row. Similarly, a gridheight or gridwidth of RELATIVE specifies the next to the last component. This is used to indicate that this component should absorb any extra space rather than the last component and is not necessary otherwise. With this technique, it is not possible to leave "holes" in the grid. See the sample program "GridBag3.java".


Altering the Grid Appearance

See and execute the sample program "GridBag1.java" for an illustration of how the various constraint variables impact the appearance of the grid.


Sample Program - GridBag1

import java.awt.*;

/**
 * 
 * This class illustrates the impact of the various constraints on the 
 * appearance of components displayed under the control of the 
 * GridBagLayout.  Thus, it must both define the initial constraints 
 * and reset the constraints when any are changed.  In a more typical
 * use of the GridBagLayout, the constraints would only be set once.
 *
 * In order to provide the user with access to the constraints, it 
 * displays a frame whose left half contains a "control panel" for 
 * changing the various constraints used in the "data panel" on the right. 
 * In order to observe the effect of changing one or more GridBag 
 * constraints, specify the new constraints and then press the "Redraw"
 * button.
 *
 * To execute this program, type "java GridBag1".
 * 
 */
public class GridBag1 extends Frame {

   /**
    *
    * This constructor creates a "control panel" in the West portion of 
    * the frame's default border layout and a "data panel" in the Center.  
    * The "control panel" will provide choice lists and entry fields 
    * which set various constraint values for the data panel on the
    * right.
    *
    */
   public GridBag1() {

      setFont(new Font("Helvetica", Font.PLAIN, 14));

      DataPanel dataPanel = new DataPanel();
      add("Center", dataPanel);

      ControlPanel controlPanel = new ControlPanel(dataPanel, this);
      add("West", controlPanel);

   }

   
   /**
    *
    * This method exits the application if the destroy event is received.  
    * This event is usually triggered because the user has pressed the 
    * close window icon.
    *
    */
   public boolean handleEvent(Event e) {

      if (e.id == Event.WINDOW_DESTROY)
         System.exit(0);

      return super.handleEvent(e);

   }


   /**
    *
    * This method creates a new instance of the class and shows it.
    *
    */
   public static void main(String args[]) {

      GridBag1 window = new GridBag1();

      window.setTitle("GridBag Sample #1");
      window.pack();
      window.show();
   }

}


/*
 * 
 * This class manages a panel of buttons which illustrate the various 
 * features of the GridBagLayout.
 *
 */
class DataPanel extends Panel {

   GridBagLayout gridbag;
   GridBagConstraints c;
   Button [] buttons = new Button[10];

   /*
    *
    * This constructor method creates the GridBagLayout and its 
    * constraints.  Then it sets up all of the buttons using the 
    * initial default values.
    *
    */
   DataPanel() {

      gridbag = new GridBagLayout();
      c = new GridBagConstraints();
      setLayout(gridbag);

      setupAllButtons(GridBagConstraints.BOTH, GridBagConstraints.CENTER, 
                      0, 0, 1);
   }

   /*
    *
    * This method sets up all buttons.  If the buttons do not already 
    * exist, then they will be created.  Otherwise, their constraints
    * will be reset as requested.
    *
    */
   void setupAllButtons(int gridFill, int gridAnchor, int gridPad, 
                        int gridInsets, int gridWeight) {

      //
      // Set the spacing parameters as requested by the user.
      //
      c.anchor = gridAnchor;
      c.fill = gridFill;
      c.ipadx = gridPad;
      c.ipady = gridPad;
      c.insets = new Insets(gridInsets, gridInsets, gridInsets, gridInsets);

      //
      // Setup the 4 buttons which occupy the first row.  These buttons 
      // initially have the same weight and will expand to fill their 
      // display area.  Button 4 must be assigned the width of "REMAINDER"
      // in order to end the row.  Button 2 will get whatever weight the 
      // user defines (initially 1).  All other buttons get the weight
      // of 1.
      //
      c.weightx = 1.0;
      makeButton(1, gridbag, c);

      c.weightx = gridWeight;
      makeButton(2, gridbag, c);

      c.weightx = 1.;
      makeButton(3, gridbag, c);

      c.gridwidth = GridBagConstraints.REMAINDER;
      makeButton(4, gridbag, c);

      //
      // Setup buttons 5 which occupies the second row all by itself.   
      // The REMAINDER constraint is still in effect from the previous row.
      //
      c.weightx = 0.;
      makeButton(5, gridbag, c);

      //
      // Setup buttons 6 and 7 which occupy the third row.  Button 6 will 
      // absorb any unused space in the row because it has the gridwidth
      // of RELATIVE.  Then button 7 will end the row because it has the 
      // gridwidth of REMAINDER.
      //
      c.gridwidth = GridBagConstraints.RELATIVE;
      makeButton(6, gridbag, c);

      c.gridwidth = GridBagConstraints.REMAINDER;
      makeButton(7, gridbag, c);

      //
      // Setup button 8 which occupies 2 rows.  Then setup buttons 9 
      // and 10 which are immediately to the right of button 8.
      //
      c.gridwidth = 1;
      c.gridheight = 2;
      c.weighty = 1.;
      makeButton(8, gridbag, c);

      c.weighty = 0.;
      c.gridwidth = GridBagConstraints.REMAINDER;
      c.gridheight = 1;
      makeButton(9, gridbag, c);

      makeButton(10, gridbag, c);
      c.gridwidth = 1;

      //
      // Invalidate the components so that they are repositioned as 
      // necessary.
      //
      invalidate();
      validate();
   }

   /*
    *
    * This method will create the button if necessary and add it to the 
    * container.  If the button already exists, it will simply reset its 
    * constraints.
    *
    */
   private void makeButton(int num, GridBagLayout gridbag, 
                           GridBagConstraints c) {

      if (buttons[num-1] == null) {
         String name = "Button "+num;
         buttons[num-1] = new Button(name);
         add(buttons[num-1]);
      }
      gridbag.setConstraints(buttons[num-1], c);
   }


}


/*
 *
 * This class manages a panel of choice lists and entry fields which 
 * enable the user to change some of the GridBagConstraints.
 *
 */
class ControlPanel extends Panel {

   //
   // Data Members
   //
   private Frame     window;
   private DataPanel dataPanel;

   private Button    redraw;
   private Choice    fill, anchor;
   private TextField internalPadding, externalPadding, button2Weight;

   private String [] fillLabel = {"Both", "None", 
                                  "Horizontal", "Vertical"};
   private int    [] fillType  = {GridBagConstraints.BOTH, 
                                  GridBagConstraints.NONE,
                                  GridBagConstraints.HORIZONTAL, 
                                  GridBagConstraints.VERTICAL};

   private String [] anchorLabel = {"Center", "North", "NorthEast", 
                            "East", "SouthEast", "South",
                            "SouthWest", "West", "NorthWest"};
   private int    [] anchorType = {GridBagConstraints.CENTER, 
                                   GridBagConstraints.NORTH, 
                                   GridBagConstraints.NORTHEAST, 
                                   GridBagConstraints.EAST, 
                                   GridBagConstraints.SOUTHEAST, 
                                   GridBagConstraints.SOUTH, 
                                   GridBagConstraints.SOUTHWEST,
                                   GridBagConstraints.WEST, 
                                   GridBagConstraints.NORTHWEST};
           

   /*
    *
    * This constructor creates the choice lists and entry fields which
    * will be used to change the data panel.  The control panel also 
    * uses a GridBagLayout for its controls.
    *
    */
   ControlPanel(DataPanel dataPanel, Frame window) {

      this.dataPanel = dataPanel;
      this.window = window;

      GridBagLayout gridbag = new GridBagLayout();
      GridBagConstraints c = new GridBagConstraints();
      setLayout(gridbag);

      //
      // Create the choice list of the various fill possibilities.
      //
      c.insets = new Insets(6, 6, 2, 6);
      fill = new Choice();
      for (int i=0; i < fillLabel.length; i++)
         fill.addItem(fillLabel[i]);
      addEntry(gridbag, c, "Fill: ", fill);

      //
      // Create the choice list of the various anchor possibilities.
      //
      c.insets = new Insets(2, 6, 2, 6);
      anchor = new Choice();
      for (int i=0; i < anchorLabel.length; i++)
         anchor.addItem(anchorLabel[i]);
      addEntry(gridbag, c, "Position: ", anchor);

      // 
      // Create the entry fields for the internal and external padding
      // and the weight to use for button #2.
      //
      internalPadding = new TextField("0", 2);
      addEntry(gridbag, c, "Int. Padding: ", internalPadding);

      externalPadding = new TextField("0", 2);
      addEntry(gridbag, c, "Ext. Padding: ", externalPadding);

      button2Weight = new TextField("1", 2);
      addEntry(gridbag, c, "Weight #2: ", button2Weight);

      //
      //  Create the "redraw" button.
      //
      c.insets = new Insets(2, 6, 6, 6);
      redraw = new Button("Redraw");
      gridbag.setConstraints(redraw, c);
      add(redraw);

   }

   /*
    *
    * This method first creates a label which is centered within its
    * cell, applies the constraints and adds the label to the 
    * container.  Then it sets the constraints for the previously
    * created data component and adds it.
    *
    */
   private void addEntry(GridBagLayout gridbag, GridBagConstraints c, 
                         String title, Component comp) {

      //
      // Create and add the label.
      //
      c.gridwidth = 1;
      Label label = new Label(title, Label.CENTER);
      gridbag.setConstraints(label, c);
      add(label);

      //
      // Add the component at the end of the row.
      //
      c.gridwidth = GridBagConstraints.REMAINDER;
      gridbag.setConstraints(comp, c);
      add(comp);

   }


   /*
    *
    * This method handles the action only from the "redraw" button.  
    * When this button is pressed, it retrieves the information from 
    * all of the fields and requests the data panel to setup the new 
    * constraints on the buttons.
    *
    */
   public boolean action(Event e, Object arg) {

      if (e.target == redraw) {
         //
         // Get the data from all of the fields.
         //
         int gridFill = fillType[fill.getSelectedIndex()];
         int gridAnchor = anchorType[anchor.getSelectedIndex()];

         int gridInternalPad = getData(internalPadding);
         int gridExternalPad = getData(externalPadding);
         int gridWeight = getData(button2Weight);

         //
         // Reset the contraints on all of the buttons and then
         // repack them in the container.
         //
         dataPanel.setupAllButtons(gridFill, gridAnchor, gridInternalPad, 
                                   gridExternalPad, gridWeight);
         window.pack();
         window.resize(window.preferredSize());
         return true;
      }
      else
         return false;

   }

  
   /*
    * 
    * This method parses the text field in order to extract its
    * numeric value.  If the field contains a blank or any other
    * non-numeric value, then it returns 0.
    *
    */
   private int getData(TextField field) {

      int data = 0;

      try {
         data = Integer.parseInt(field.getText());
      } catch (Exception e) {}

      return data;
   }


   /* 
    *
    * The paint method has been overridden in order to draw a raised
    * rectangular border around the control panel.
    *
    */
   public void paint(Graphics g) {

      Dimension d = size();
      g.setColor(getBackground());
      g.draw3DRect(0, 0, d.width -2, d.height-2, true);
      g.draw3DRect(3, 3, d.width -8, d.height-8, false);

   } 

}

//*************************< End of GridBag1.java >************************


Sample Program - GridBag2

import java.awt.*;

/**
 *
 * This class illustrates the use of the GridBagLayout and
 * the positioning of controls by specifing the "gridx" 
 * and "gridy" constraints.
 *
 * It will draw a grid of buttons which looks like this:
 *
 *    1    2    3
 *    4    5    6      
 *    7    8    9
 *        11
 *    13       15
 *
 * In order to execute this program, type "java GridBag2".
 *
 */
public class GridBag2 extends Frame {

   public GridBag2() {

      setFont(new Font("Helvetica", Font.PLAIN, 14));
      GridBagLayout gridbag = new GridBagLayout();
      GridBagConstraints c  = new GridBagConstraints();
      setLayout(gridbag);

      c.fill = GridBagConstraints.BOTH;
      c.weightx = 1.;

      addInXYOrder(gridbag, c);

      addInRandomOrder(gridbag, c);

   }


   /**
    *
    * This method adds the first 9 buttons in order from left to
    * right and from top to bottom.
    *
    */
   protected void addInXYOrder(GridBagLayout gridbag, GridBagConstraints c) {

      for (int i=0; i < 9; i++) {

         c.gridx = i%3;
         c.gridy = i/3;
         String buttonLabel = "Button "+(i+1);
         makeButton(buttonLabel, gridbag, c);
      }


      return;

   }


   /**
    *
    * This method adds the 3 remaining buttons in the order
    * Button 15, Button 13 and then Button 11.  This is done
    * in order to illustrate the order independence and the
    * creation of "holes".
    *
    */
   protected void addInRandomOrder(GridBagLayout gridbag, 
                                   GridBagConstraints c) {

      c.gridx = 2;
      c.gridy = 4;
      makeButton("Button 15", gridbag, c);

      c.gridx = 0;
      c.gridy = 4;
      makeButton("Button 13", gridbag, c);

      c.gridx = 1;
      c.gridy = 3;
      makeButton("Button 11", gridbag, c);

      return;

   }


   /**
    *
    * This method creates a single button with the specified
    * name, assigns it the current constraints and then adds it
    * to the container.
    *
    */
   protected void makeButton(String name,
                             GridBagLayout gridbag,
                             GridBagConstraints c) {

      Button button = new Button(name);
      gridbag.setConstraints(button, c);
      add(button);
   }


   /**
    *
    * This method exits the system when the WINDOW_DESTROY event
    * is generated.  This usually occurs because the user has
    * pressed the close icon.
    *
    */
   public boolean handleEvent(Event e) {

      if (e.id == Event.WINDOW_DESTROY)
         System.exit(0);

      return super.handleEvent(e);

   }

   /**
    *
    * This method creates an instance of the class and shows it.
    *
    */
   public static void main(String args[]) {

      GridBag2 window = new GridBag2();

      window.setTitle("GridBag Sample #2");
      window.pack();
      window.show();
   }

}

//*************************< End of GridBag2.java >************************


Sample Program - GridBag3

import java.awt.*;

/**
 *
 * This class illustrates the use of the GridBagLayout and
 * the positioning of controls using the "relative" approach.
 * Under this approach, "gridx" and "gridy" are set to -1 and
 * each row is terminated by specifying a gridwidth of REMAINDER.
 *
 * It will draw a grid of buttons which looks like this:
 *
 *    1    2    3
 *    4    5    6      
 *    7    8    9
 *
 * In order to execute this program, type "java GridBag3".
 *
 */
public class GridBag3 extends Frame {

   public GridBag3() {

      setFont(new Font("Helvetica", Font.PLAIN, 14));
      GridBagLayout gridbag = new GridBagLayout();
      GridBagConstraints c  = new GridBagConstraints();
      setLayout(gridbag);

      c.fill = GridBagConstraints.BOTH;
      c.weightx = 1.;

      addInRelativeOrder(gridbag, c);

      return;
   }


   /**
    *
    * This method adds a series of 9 buttons using the relative
    * approach.  The buttons are added from left to right and
    * from top to bottom.  The last button in each row must have
    * a gridwidth of REMAINDER.
    *
    */
   protected void addInRelativeOrder(GridBagLayout gridbag,
                                      GridBagConstraints c) {

      c.gridx = GridBagConstraints.RELATIVE;
      c.gridy = GridBagConstraints.RELATIVE;

      for (int i=0; i < 9; i++) {
         String buttonLabel = "Button "+(i+1);
         if (i%3 == 2)
            c.gridwidth = GridBagConstraints.REMAINDER;
         else
            c.gridwidth = 1;
         makeButton(buttonLabel, gridbag, c);

      }

   }

   /**
    *
    * This method creates a single button with the specified
    * name, assigns it the current constraints and then adds it
    * to the container.
    *
    */
   protected void makeButton(String name,
                             GridBagLayout gridbag,
                             GridBagConstraints c) {

      Button button = new Button(name);
      gridbag.setConstraints(button, c);
      add(button);
   }


   /**
    *
    * This method exits the system when the WINDOW_DESTROY event
    * is generated.  This usually occurs because the user has
    * pressed the close icon.
    *
    */
   public boolean handleEvent(Event e) {

      if (e.id == Event.WINDOW_DESTROY)
         System.exit(0);

      return super.handleEvent(e);

   }

   /**
    *
    * This method creates an instance of the class and shows it.
    *
    */
   public static void main(String args[]) {

      GridBag3 window = new GridBag3();

      window.setTitle("GridBag Sample #3");
      window.pack();
      window.show();
   }

}

//*************************< End of GridBag3.java >************************