Way2Java

Java AWT GridBagLayout Manager

This is the king of all layout managers because it can handle almost any type of layout arrangement. It is more flexible and at the same time more complex to use. This is an extension of GridLayout manager. Both grid layout and grid bag layout use the concept of grid of cells (spread between rows and columns). This layout manager is used when the components are dissimilar in size as in the case of a Calculator buttons design. In GridLayout, one component occupies only one cell but in GridBagLayout, one component can occupy more than one cell either horizontally or vertically or both.

Comparison of GridLayout with GridBagLayout

A grid bag layout differs from grid layout in the following:

  1. A component can occupy more than one cell in the grid.
  2. The proportions between different rows and columns need not be equal.
  3. A component need not occupy or fill the complete cell.
  4. Component inside the cell can be arranged in different ways (this possibility arises when the component does not occupy the complete space of the cell).

class GridBagLayout

GridBagLayout manager is represented by a class called GridBagLayout from java.awt package.

Following is the class signature

public class GridBagLayout extends Object implements LayoutManager2, Serializable

Following are some important methods

  1. void setConstraints(Component comp, GridBagConstraints con): Sets the component as per the GridBagConstraints, con.
  2. GridBagConstraints getConstraints(Component comp): Returns all the properties of the component as an object of GridBagConstraints.

GridBagConstraints

It is a helper class used in combination with GridBagLayout object. This class sets the properties to a component. GridBagLayout manager lays the components in a container as per the properties set by the GridBagConstraints object. GridBagConstraints class includes methods and variables to set the properties of a component – its placement, dimension, alignment etc. The ultimate size and position of a component depends on the relationship between the grid bag and the constraints.

Following is the class signature

public class GridBagConstraints extends Object implements Cloneable,
Serializable

Steps of using GridBagLayout

To simplify the procedure of using GridBagLayout manager, it is better to formulate some steps, like you followed for Menus.

  1. Set the layout to the grid bag layout manager (creating an object and setting layout).
  2. Create an instance of GridBagConstraints.
  3. Set the constraints (properties) for each component separately.
  4. Inform the layout manager about the component and its constraints.
  5. Add the component to the container.

Fields of GridBagConstraints

Always the component to be added to the container is associated with GridBagConstraints object which dictates the properties of the component in terms of position and size. The GridBagConstraints includes a big family of public fields (variables) that sets the constraints (properties) to a component.

Following are some important fields

>

Variable Description
gridx, gridy These variables are used to specify the location where the component is to be placed. For example, the top-left cell location is specified as gridx = 0 and gridy = 0. If no values for these variables are specified, the layout manager assumes them to be as GridBagConstraints.RELATIVE which means the component is to be placed next to the existing one (it is relative placement: either to the right or below the existing one).
gridwidth, gridheight These variables are used to give the size of the component in terms of cells. The default value is 1, if no value is specified. Assigning GridBagConstraints.REMAINDER to these variables means, the component getting added is the last one in its row.
fill This field is used when the component’s display area is larger than the component’s size. It tells whether to resize the component or not when the frame is resized. The value can be one of the following.
  1. GridBagConstraints.HORIZONTAL: Component grows horizontally
  2. GridBagConstraints.VERTICAL: Component grows vertically
  3. GridBagConstraints.BOTH: Component grows both ways
  4. GridBagConstraints.NONE: Component does not grow at all
anchor This variable specifies the placement (or location) of the component within the cell when the component does not fill the whole cell. The value can by any one of the following.
  1. GridBagConstraints.NORTH
  2. GridBagConstraints.NORTHEAST
  3. GridBagConstraints.EAST
  4. GridBagConstraints.SOUTHEAST
    GridBagConstraints.SOUTH
  5. GridBagConstraints.SOUTHWEST
  6. GridBagConstraints.WEST
  7. GridBagConstraints.NORTHWEST
  8. GridBagConstraints.CENTER (the default one)
ipadx, ipady ipadx pixels are added to the left and right of the minimum size of the component and ipady pixels are added to the top and bottom.
insets specifies the empty space between the container border and the components.
weightx, weighty distribute the space when the container expands. The GridBagLayout distributes the space between the columns horizontally or vertically as per the weights of weightx and weighty. The columns or cells with more weight get more space. The cells with 0 weight value will not get any extra space. The range of values must be 0.0 to 1.0. The default value of these fields are 0 and when specified it must be a non-negative value. The actual behavior is also dependent on the fill factor.


Using Two Properties

To start with, let us make a simple program with two buttons. To understand the constraints, only two properties girdx, gridy and fill are used.

import java.awt.*;   
public class TwoConstraints extends Frame  
{
  public TwoConstraints()  
  {
    GridBagLayout gbl = new GridBagLayout();    // create an object of grid bag layout
    GridBagConstraints gbc = new GridBagConstraints(); //grid bag constraints object 
    setLayout(gbl);                          

    Button b1 = new Button("Button 1");             // start giving constraints to button 1
    gbc.weightx = 1.0;              // maximum values are set to weight variables initially
    gbc.weighty = 1.0;
    gbc.fill = GridBagConstraints.BOTH;                   // component grows both ways
    gbl.setConstraints(b1, gbc);       // informing the grid bag layout to set the button b1 
    add(b1);                          // as per gbc constraints

    Button b2 = new Button("Button 2");
    gbc.weightx = 1.0;               // maximum values are set to weight variables initially
    gbc.weighty = 1.0;
    gbc.fill = GridBagConstraints.BOTH; // this component also expands both ways
    gbl.setConstraints(b2, gbc);  // informing the grid bag layout about the button b2
    add(b2);                                 // and its constraints

    setTitle("TwoConstraints");  
    setSize(300, 300);   
    setVisible(true);
  }
  public static void main(String args[])   
  {   
    new TwoConstraints();  
  }
}

Output screen of TwoConstraints.java

Both the buttons in the above program are of the same size and initially set with same constraints. gridx and gridy constraints are not set and will take the default values. For the first button it is 0 and 0 and for the second button it is relative to the first button (means added implicitly next to the previous).

For both the buttons weightx and weighty are given same values. To understand the effect of these variables, keep one button values as it is and change the other button values of both weightx and weighty (at the beginning change one only). With all the possible combinations change and see the output. Remember the values must be within 0.0 and 1.0.

To try with other variable, come back to the original program (with original values). Next attack the other variable fill. Keep one button’s constraints as it is and change the other one. The other possible values for fill are as follows:

GridBagConstraints.HORIZONTAL: Component grows horizontally
GridBagConstraints.VERTICAL: Component grows vertically
GridBagConstraints.BOTH: Component grows both ways
GridBagConstraints.NONE: Component does not grow at all

When satisfied with the observation, change both weightx, weighty and fill and observe the effect. This is very essential to understand the next program.

Using all the Properties

The grid bag layout is based on the idea of rows and columns. When you are placing the components in grid layout or flow layout, the order of addition is very important. But is not the case in GridBagLayout because we specify the cell position of the component in terms of gridx (column number) and gridy (row number). That is, we can add the last button and then the first button.

In the following program, 7 buttons of different sizes are created and added.

import java.awt.*;    
import java.awt.event.*;
public class IrregularSizeButtons extends Frame  
{
  public IrregularSizeButtons()   
  {
    GridBagLayout gbl = new GridBagLayout();
    GridBagConstraints gbc = new GridBagConstraints();
    setLayout(gbl);
    Button b ;    // a reference variable of  Button which can be instantiated many times if reinstantiated, the earlier object is garbage collected
    gbc.gridx = 0;   	             // start setting the constraints                                                           
    gbc.gridy = 0;
    gbc.gridwidth = 1;
    gbc.gridheight = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;   // grows horizontally

    b = new Button("First");
    gbl.setConstraints(b, gbc);
    add(b);

    b = new Button("Second");
    gbc.gridx = 1;            // gbc.gridy = 0 is taken from the previous button.  If ones the the constraint is set, it will remain same in the        
    gbl.setConstraints(b, gbc);         // subsequent code, unless it is changed
    add(b);

    b = new Button("Third");
    gbc.gridx = 2;
    gbc.gridwidth = GridBagConstraints.REMAINDER;    // REMAINDER indicates to 
    gbl.setConstraints(b, gbc);      // the layout that this component is last one in the row
    add(b);

    b = new Button("Fourth");
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbl.setConstraints(b, gbc);                           
    add(b);   

    b = new Button("Fifth");
    gbc.gridwidth = 1;
    gbc.gridy = 2;
    gbl.setConstraints(b, gbc);
    add(b);

    b = new Button("Six");
    gbc.gridx = 1;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbl.setConstraints(b, gbc);
    add(b);

    b = new Button("Seven");
    gbc.gridx = 0;
    gbc.gridy = 3;
    gbc.gridwidth = GridBagConstraints.REMAINDER ;
    gbl.setConstraints(b, gbc);
    add(b);
  }
  public static void main)String args[])   
  {
    Frame f = new IrregularSizeButtons();   
    f.setTitle("Creating Uneven size buttons");  
    f.setSize(300,300);  
    f.setVisible(true);
  }
}
Output screen of IrregularSizeButtons.java

Observe the button sizes. The first three and fifth take only one cell. The fourth and seventh occupies 3 cells and sixth one takes two cells. This type of irregular size components’ creation is possible with GidBagLayout only.

The variables gridx and gridy give the location where the component is to be positioned. Other way, they give the cell number. gridwidth and gridheight give the number of cells the component should occupy horizontally and vertically. These variables give different sizes to the components (in terms of cells). Another style of giving the width of the component is as in the following format.

gbc.gridwidth = GridBagConstraints.REMAINDER;

REMAINDER indicates that the component should occupy all the remaining cells available in the row. This is a better way of giving the size (or adding) if the component is the last one added in the row. By this, the GridBagLayout comes to an understanding that the row is over.

gbc.fill = GridBagConstraints.HORIZONTAL;

The above statement tells the GridBagLayout manager that the component can fill all the remaining cells in the row. It permits the component to occupy the remaining space of the row. The fill value HORIZONTAL must be used in combination with gridwidth value as REMAINDER; else no meaning.


Using Anchor Constraint Only

In the following program, when a button is clicked, the center button is anchored (change its position within the cell) accordingly. The center button does not occupy the complete cell. As it does not occupy the complete space of the cell, it can move around in the cell, as per the action given.

import java.awt.*;   
import java.awt.event.*;
public class UsingAnchorConstraint extends Frame  implements ActionListener  
{
  Button n, nw, w, ne, e, s, se, sw, cb ;
  GridBagLayout gbl ;  GridBagConstraints gbc ;

  public UsingAnchorConstraint()
  {
    gbl= new GridBagLayout();
    gbc = new GridBagConstraints();
    setLayout(gbl);
    setBackground(Color.cyan);
    gbc.insets = new Insets(5,5,5,5);
                                         // add the center button at the beginning as its constraints are very different from the rest
    cb = new Button("C");
    gbc.gridx = 1;    
    gbc.gridy = 1;
    gbc.fill = GridBagConstraints.NONE;    
    gbl.setConstraints(cb, gbc);
    add(cb);
    cb.addActionListener(this);
    cb.setBackground(Color.black); 
    cb.setForeground(Color.white);
                                    // add the first row first button
    nw = new Button("North West");
    gbc.gridx = 0;    
    gbc.gridy = 0;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.weightx = 1.0; gbc.weighty = 1.0;
    gbl.setConstraints(nw, gbc);
    add(nw);  
    nw.addActionListener(this);
                                   // add the first row second button
    n = new Button("North");
    gbc.gridx = 1;   gbc.gridy = 0;
    gbc.weightx = 1.0;   gbc.weighty = 1.0;
    gbl.setConstraints(n, gbc);
    add(n) ;  
    n.addActionListener(this);
                                    // add the first row third button
    ne = new Button("North East");
    gbc.gridx = 2;  gbc.gridy = 0;    // other constraints are taken from the earlier settings
    gbl.setConstraints(ne, gbc);
    add(ne);  
    ne.addActionListener(this);
                                   // add the second row first button 
    w = new Button("West");
    gbc. gridx  = 0;    gbc.gridy  = 1;
    gbl.setConstraints(w, gbc);
    add(w);  
    w.addActionListener(this);
                                      // add the second row third button(second is added already at the beginning: center button)
    e = new Button("East");
    gbc.gridx = 2;   gbc.gridy = 1;
    gbl.setConstraints(e, gbc);
    add(e);  
    e.addActionListener(this);
                                   // add the third row first button
    sw = new Button("South West");
    gbc.gridx = 0;   gbc. gridy = 2;
    gbl.setConstraints(sw, gbc);
    add(sw);  
    sw.addActionListener(this);
                                   // add the third row second button
    s = new Button("South");
    gbc.gridx = 1;   gbc.gridy = 2;
    gbl.setConstraints(s, gbc);
    add(s);  
    s.addActionListener(this);
                                    // add the third row third button
    se = new Button("South East");
    gbc.gridx = 2;  gbc.gridy = 2;
    gbl.setConstraints(se, gbc);
    add(se);  
    se.addActionListener(this);
  }                                           // constructor closing
  public void actionPerformed(ActionEvent e)   
  {
                   // click a border button and the center button is positioned accordingly
    String str = e.getActionCommand() ;
    if(str.equals("North West"))           
        gbc.anchor = GridBagConstraints.NORTHWEST;
    else if(str.equals("North"))            
        gbc.anchor = GridBagConstraints.NORTH;                              
    else if(str.equals("West"))             
        gbc.anchor = GridBagConstraints.WEST;
    else if(str.equals("North East"))    
        gbc.anchor = GridBagConstraints.NORTHEAST;
    else if(str.equals("C"))      // clicking the center buttons also
        gbc.anchor = GridBagConstraints.CENTER;
    else if(str.equals("East"))              
        gbc.anchor = GridBagConstraints.EAST;
    else if(str.equals("South West"))   
        gbc.anchor = GridBagConstraints.SOUTHWEST;
    else if(str.equals("South"))            
        gbc.anchor = GridBagConstraints.SOUTH ;
    else if(str.equals("North East"))     
        gbc.anchor = GridBagConstraints.NORTHEAST;
    else if(str.equals("South East"))    
        gbc.anchor = GridBagConstraints.SOUTHEAST;

                         // the constraints of the center button are re-defined (in the following 
                         // code) as their values are changed due to the other buttons clicks.  

    gbc.gridx = 1;  gbc.gridy = 1;
    gbc.fill = GridBagConstraints.NONE;
    gbl.setConstraints(cb, gbc);
      
    invalidate(); 
    validate();                                  
  }  
  public static void main(String args[])
  {                                                                                          
    Frame f = new UsingAnchorConstraint();                                                      
    f.setTitle("Using Anchor Constraint");
    f.setSize(300,300);  
    f.setVisible(true);
  }
}
Output screen of UsingAnchorConstraint.java

gbc.insets = new Insets(5, 5, 5, 5);

The insets variable of GridBagConstraints class gives the space between the components and the border of the frame (not in between the components). The parameter order is top, left, bottom and right (anti-clockwise). All are given 5 pixels only.

gbc.fill = GridBagConstraints.NONE;

The above fill variable dictates the component should not grow to the full size of the cell.

gbc.fill = GridBagConstraints.BOTH;

The above fill variable dictates the component should grow to the full size of the cell both horizontally and vertically. That is, the component occupies the whole cell. In the above program, except the center component, each component occupies complete cell.

gbc.weightx = 1.0; gbc.weighty = 1.0;

weightx and weighty fields control the space distribution among cells when the frame is resized so that the frame is larger than the actual space required for the cells. The maximum value is 1.0 and means it gives more weight (preference) to the cell to grow. All the components are given 1.0 except the center one, “C“. The center one takes a default value of 0 and means does not grow when the frame is resized.

gbc.anchor = GridBagConstraints.NORTHWEST;

When a button is clicked, the center button is repositioned within its cell. The above statement places the center button in the North West corner of the cell. Like this, the position can be 9 ways – 4 sides, 4 corners and center.

invalidate();
alidate();

Whenever a layout is disturbed either by adding a new component or deleting an existing component, these methods are to be called by the programmer. The invalidate() method invalidates the existing layout setup and validate() method validates the components with the new setup.