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:
- A component can occupy more than one cell in the grid.
- The proportions between different rows and columns need not be equal.
- A component need not occupy or fill the complete cell.
- 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
- void setConstraints(Component comp, GridBagConstraints con): Sets the component as per the GridBagConstraints, con.
- 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.
- Set the layout to the grid bag layout manager (creating an object and setting layout).
- Create an instance of GridBagConstraints.
- Set the constraints (properties) for each component separately.
- Inform the layout manager about the component and its constraints.
- 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.
|
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.
|
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();
}
}
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);
}
}
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);
}
}
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.