Example
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:
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.
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.
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.
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.
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.
A good example of this is Sort property editor shown at the end of this section. All of the container's components can fit into two columns except the three buttons at the bottom. If you try to add these buttons individually in the row, GridBagLayout does not handle them well. Extra columns are created which affect the placement of the components above it. To simplify the grid and guarantee the buttons would behave the way we expected when the container was resized at runtime, we used a GridLayout panel two columns wide to hold the buttons.
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,
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.
Menu Command | Action |
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. |
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.
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
|
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.
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.) |
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.
You can also specify the fill constraint in the Constraints property editor.
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). |
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.
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:
gridx=nn, gridy=nn
GridBagConstraints.RELATIVE (-1)
|
gridx=1, gridy=1
|
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.
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.) |
insets = new Insets(0,0,0,0) |
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.
When an inset value is greater than zero, the UI Designer displays a pair of blue nibs for that inset, one on the edge of the cell and one on the edge of the display area. The size of the inset is the distance (number of pixels) between the two nibs. Grab either nib to change the size of the inset.
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
|
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.
Before:
After:
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
|
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.
Examples of how weight constraints affect components' behavior:
The three pictures below demonstrate this.
In the first example, all the components in the GridBagLayout panel have a weight constraint value of zero. Because of this, the components are clustered in the center of the GridBagLayout panel, with all the extra space in the panel distributed between the outside edges of the grid and the panel. The size of the grid is determined by the preferred size of the components, plus any insets and padding (ipadx or ipady).
Next, a horizontal weight constraint of 1.0 is specified for the ListControl. Notice that as soon as one component is assigned any weight, the UI design is no longer centered in the panel. Since a horizontal weight constraint was used, the GridBagLayout manager takes the extra space in the panel that was previously on each side of the grid, and puts it into the cell containing the ListControl. Also notice that the ListControl did not change size.
Finally, if a horizontal fill is then added to the ListControl, the component expands to fill the new horizontal dimension of the cell.
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 .
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.
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.