Java Notes
java.awt.GridBagLayout
Description
GridBagLayout lays out components based on a grid with rows and columns that need not all be the same size. If you're familiar with HTML tables, you'll feel comfortable with the idea. Unfortunately, GridBagLayout is infernally awkward and error-prone to use. After reading some of this you might want to see example code at Example: GridBagLayout.
Abandon hope, all ye who use GridBagLayout
Altho GridBagLayout can produce acceptable results, it's not a happy story.
- It is very difficult to work with because eleven constraint values are used for each component! These constraint values are bundled in a java.awt.GridBagConstraints object. Fortunately, most of them have reasonable defaults.
- The layout doesn't have features which specifically help to use Sun's (or anyone else's) Human Interface Guidelines, for example in handling gaps.
- Spacing is specified in pixels, which provides no flexibility for screen resolution and font changes.
- I like this quote from Otaku, Cedric's blog: "GridBagLayout is an absolute disaster and the perfect example of something that is completely flawed and violates with a stunning regularity the principle of least surprise."
- Everyone who has touched GridBagLayout will enjoy Totally Gridbag, little bit of Flash foolishness - madbean.com/blog/2004/17/totallygridbag.html
- Some prefer to call it "GridBugLayout".
Subpanels for unrelated components. An entire window may require use of nested panels -- don't try to force everything into one giant GridBagLayout. If some groups of components (eg, radio buttons, groups of buttons, checkboxes) are unrelated to alignment with other components, put them in their own panel and use an appropriate layout (often GridLayout).
Unequal rows and columns
The underlying idea is rows and columns, similar to HTML tables.
- Rows and columns don't all have to be same size. The size of each row and column is adjusted depending on maximum component size in the row/column and their constraints.
- A component display area may span several rows and/or columns. Describe this area by giving the row, column, width (in columns), and height (in rows).
- A components doesn't have to fill its display area; constraints describe how to align it within its area.
Three categories of constraint parameters
GridBagLayout performs three functions using values from the
GridBagConstraints parameter in the add()
method.
The names [note the case violations of the standard Java naming convention]
are the following.
- Grid position, width and height describe the display area..
gridx
,gridy
,gridwidth
, andgridheight
. - Position within the display area.
fill
,anchor
,insets
,ipadx
, andipady
. - Identifying rows and columns which receive extra space on expansion.
weightx
, andweighty
.
Constructor
JPanel p = new JPanel(new GridBagLayout());
or
JPanel p = new JPanel(); p.setLayout(new GridBagLayout());
Do not give the number of rows and columns when you create a new GridBagLayout. The are computed by the layout manager as a consequence of what you add.
Adding a component
Components are added to JPanel p like this:
p.add(component, constraintObj);
Constraint parameters are instance fields in a GridBagConstraints object. The add() method clones (copies) the constraint object, so typically the same GridBagConstraints object is reused to pass constraints for the next component. It is common to use only one GridBagConstraints object to add all components, changing fields as necessary between adds, but this practice also leads to many errors and code which is difficult to change.
GridBagConstraints fields
The fields can divided into three groups:
- Necessary - row and column coordinates, width and height in terms of rows and columns
- Describe the location and size (in rows and columns)
of the component using
gridx, gridy, gridwidth
, andgridheight
. - Common - expandability and alignment
- If a column or row can use extra space when a window is expanded,
set
weightx
andweighty
to 1.0; you will rarely want to use other values.Use
fill
depending on what the type of component is. For example, a JTextField can usually grow horizontally, so you would usegbc.fill = GridBagConstraints.HORIZONTAL;
to allow it to stretch.Use
anchor
to tell which edges of the display area a component should be attached to. - Less common - surrounding spacing
- You can also control the space around a component with
ipadx
andipady
.To control the amount of unused space around a component, use
insets
.
GridBagConstraints attribute summary
gridx |
The int column (gridx ) and row (gridy )
of the component. If requires more than
one cell (gridwidth or gridheight > 1), this is the
coordinate of the top-left cell. The row and columns start
at zero. The value GridBagConstraints.RELATIVE
places the component in the next position.
|
gridwidth |
Number of columns or rows the component occupies.
GridBagConstraints.REMAINDER indicates that
this component should fill out all rows or columns to the end.
Default 1. Note these names violates naming standards (second
word not capitalized).
|
weightx |
These double variables (default value 0) are used in calculating where
space is allocated in rows and columns when a window is resized.
extra space should be allocated in a column horizontally (weightx) and
row vertically (weighty).
A column width is originally calculated as the maximum width of
the preferred sizes of the components in that column. If a component
is narrower than the column width, the value of the Extra horizontal space is allocated to a column
in proportion to the maximum |
fill |
Fill specifies how the component should expand within its display area
if the area width/height is larger than its preferred size.
GridBagConstraints.NONE // Can't expand (Default) GridBagConstraints.VERTICAL // Expand vertically GridBagConstraints.HORIZONTAL // Expand horizontally GridBagConstraints.BOTH // Expand vertically and horizontally For example, a text field typically expands horizontally
( |
anchor |
If the component doesn't occupy its entire display area, anchor
specifies where it should be placed.
The location is usually given as a compass direction.
(A relative system which works for both right-to-left
and left-to-right languages is also available).
GridBagConstraints.CENTER (the default), GridBagConstraints.NORTH GridBagConstraints.SOUTH GridBagConstraints.NORTHEAST GridBagConstraints.SOUTHWEST GridBagConstraints.EAST GridBagConstraints.WEST GridBagConstraints.SOUTHEAST GridBagConstraints.NORTHWEST |
insets |
A java.awt.Insets object adds padding space to the component.
Insets should be rarely used because they often produce bad results,
with the exception of JPanels and JLabels.
The constructor parameters
(in pixels) specify the top, left, bottom, right.
For example,
gbc.insets = new Insets(10, 5, 10, 4);Default value: Insets(0,0,0,0). |
ipadx |
These int fields specify an increase or decrease in the horizontal and/or vertical preferred size of the component. Default value 0. Negative values can be used to tighten the spacing. These values are rarely useful, altho they can be used for fine-tuning spacing. |
Java Idiom
It's common to write a utility method which sets the fields of a GridBagConstraints object. For example,
GridBagConstraints gbc = new GridBagConstraints(); . . . private void set_gbc(int row, int column, int width, int height, int fill) { gbc.gridy = row; gbc.gridx = column; gbc.gridwidth = width; gbc.gridheight = height; gbc.fill = fill; // GridBagConstraints.NONE .HORIZONTAL .VERTICAL .BOTH // leave other fields (eg, anchor) unchanged. } . . . set_gbc(3, 2, 2, 1, GridBagConstraints.HORIZONTAL); gbc.insets = new Insets(3,3,3,3); // put spacing around this field. p.add(myTextField, gbc);
Adding a component
To add myField to the third row (2) and first column (0), where the button will be one grid cell wide and one high, and it will be able to expand horizontally, do this:
set_gbc(2, 0, 1, 1, GridBagConstraints.HORIZONTAL); gridbag.setConstraints(myField, gbc); panel.add(myField);
Opinion
GridBagLayout is not a nice piece of software. The GridBagConstraints object is awkward to use. It allows you to make careless mistakes in the layout without warnings or error messages. There is little good documentation on how the parameters are used. A better version of it would be very welcome.
Consider using a better layout manager. See Alternate Layout Managers.
Some convenience classes for working with GridBaglayout
The difficulties of using GridBagLayout have spawned hundreds of convenience classes for dealing with it. Here are some.
- www.horstmann.com/articles/Taming_the_GridBagLayout.html is Cay Horstmann's convenience class for working with GridBagLayout.
- Evan Summer's Swing and Roundabouts 4: Grid Bag Grease (weblogs.java.net/blog/evanx/archive/2006/07/swing_and_round_1.html)
- Packer at https://packer.dev.java.net/.
- The book Absolute Java by Walter Savitch has a helper class called GriddedPanel by James Tan.
- xnap.sourceforge.net/apidocs/org/xnap/gui/util/GridBagHelper.html
- ulc-community.canoo.com/layout/docs/api/com/canoo/ulc/community/layout/application/package-summary.html