GridBagLayout


To fine-tune a layout, you will be forced to work with GridBagLayout, a highly configurable but more complex layout manager. GridBagLayout is similar to GridLayout in that it lets you organize components in a grid of rectangles. However, GridBagLayout gives you far more control. First, each rectangle is not fixed in sizeit is generally sized according to the default, or "preferred" size of the component it contains. Components can span multiple rows or columns.

The modified createFieldsPanel code shows how to lay out labels and fields using a GridBagLayout. (The code in the method presumes that you have statically imported java.awt.GridBagConstraints.*.)

 JPanel createFieldsPanel() {    GridBagLayout layout = new GridBagLayout();    JPanel panel = new JPanel(layout);    int columns = 20;    JLabel departmentLabel =       createLabel(DEPARTMENT_LABEL_NAME, DEPARTMENT_LABEL_TEXT);    JTextField departmentField =       createField(DEPARTMENT_FIELD_NAME, columns);    JLabel numberLabel =       createLabel(NUMBER_LABEL_NAME, NUMBER_LABEL_TEXT);    JTextField numberField =       createField(NUMBER_FIELD_NAME, columns);    layout.setConstraints(departmentLabel,       new GridBagConstraints(          0, 0,  // x, y          1, 1,  // gridwidth, gridheight          40, 1, // weightx, weighty          LINE_END, //anchor          NONE, // fill          new Insets(3, 3, 3, 3), // top-left-bottom-right          0, 0)); // padx, ipady    layout.setConstraints(departmentField,       new GridBagConstraints(1, 0, 2, 1, 60, 1,          CENTER, HORIZONTAL,          new Insets(3, 3, 3, 3), 0, 0));    layout.setConstraints(numberLabel,       new GridBagConstraints(0, 1, 1, 1, 40, 1,          LINE_END, NONE,          new Insets(3, 3, 3, 3), 0, 0));    layout.setConstraints(numberField,       new GridBagConstraints(1, 1, 2, 1, 60, 1,          CENTER, HORIZONTAL,          new Insets(3, 3, 3, 3), 0, 0));    panel.add(departmentLabel);    panel.add(departmentField);    panel.add(numberLabel);    panel.add(numberField);    return panel; } 

After creating a GridBagLayout and setting it into the panel, you call the method setConstraints on the layout for each widget to add. The setConstraints method takes two parameters: a Component object and a GridBagConstraints object. A GridBagConstraints object contains several constraints for the Component object. This table very briefly summarizes the constraints (see the API documentation for complete details):

gridx/gridy

The cell at which to begin drawing the component. The upper left cell is 0, 0.

gridwidth/gridheight

The amount of rows or columns the component should span. The default value is 1 for each, meaning that a component takes a single cell.

weightx/weighty

The weighting constraint is used to determine how much of the additional space is allocated to a component if space remains after laying out all the components in a row or column.

anchor

The anchor constraint is used to determine how it is placed within the cell if a component is smaller than its display area. The default is GridBagConstraints.CENTER.

fill

The fill constraint specifies how the component should grow to fill the display area if a component is smaller than its display area. Values are NONE (don't resize), HORIZONTAL, VERTICAL, and BOTH.

insets

Uses an Insets object to specify the space between a component and the edges of its display area.

ipadx/ipady

Specifies how much space to add to the minimum size of a component.


Each of the fields in GridBagConstraints is public. You can construct a GridBagConstraints object with no parameters, then set individual fields as necessary. Or, as in the listing for createFieldsPanel, you can specify every possible constraint using the alternate GridBagConstraints constructor.

The best tactic is to sketch, on paper or whiteboard, a grid representing how you want the output to look. Use the gridx/gridy and gridwidth/gridheight constraints to determine the relative sizes and positions of the components. Then concentrate on the anchor and fill aspects of each component. Code the layout to these sketched specifications and modify if necessary. You can then experiment with the insets and weightx/weighty constraints (and occasionally the ipadx/ipadx constraints) to tweak the spacing between components.

Obviously there is a lot of redundancy in createFieldsPanel. The following code is modestly refactored.

 JPanel createFieldsPanel() {    GridBagLayout layout = new GridBagLayout();    JPanel panel = new JPanel(layout);    int columns = 20;    addField(panel, layout, 0,       DEPARTMENT_LABEL_NAME, DEPARTMENT_LABEL_TEXT,       DEPARTMENT_FIELD_NAME, columns);    addField(panel, layout, 1,       NUMBER_LABEL_NAME, NUMBER_LABEL_TEXT,       NUMBER_FIELD_NAME, columns);    return panel; } private void addField(    JPanel panel, GridBagLayout layout, int row,    String labelName, String labelText,    String fieldName, int fieldColumns) {    JLabel label = createLabel(labelName, labelText);    JTextField field = createField(fieldName, fieldColumns);    Insets insets = new Insets(3, 3, 3, 3); // top-left-bottom-right    layout.setConstraints(label,       new GridBagConstraints(          0, row,  // x, y          1, 1,  // gridwidth, gridheight          40, 1, // weightx, weighty          LINE_END, //anchor          NONE, // fill          insets, 0, 0)); // padx, ipady    layout.setConstraints(field,       new GridBagConstraints(1, row,          2, 1, 60, 1, CENTER, HORIZONTAL,          insets, 0, 0));    panel.add(label);    panel.add(field); } 

The onerous nature of such code should drive you in the direction of extreme refactoring. Consider replacing repetition in the construction of GridBagConstraints objects by using a simplified utility constructor. If you need to represent more than a couple of fields and associated labels, consider representing each pair using a data class. You can then represent the entire set of fields in a table, iterating through it to create the layout.

Figure 9 shows a layout that is getting close to being acceptable. Resize it to see how the field components fill to their display area.

Figure 9. Using GridBagLayout


As of Java 1.4, Sun introduced the SpringLayout class. This layout manager is primarily designed for the use of GUI composition tools. The basic concept of SpringLayout is that you define a layout by tying the edges of components together using constraints known as springs.

In CoursesPanel, you might create a spring to attach the west (left) edge of the department text field to the east (right) edge of the department label. The spring object attaching the two components is a fixed five pixels in size. Another spring might attach the east edge of the department text field to the east side of the panel itself, also separated by a spring of fixed length. As the panel grows in width, the department text field would grow accordingly.

Creating a SpringLayout by hand is fairly easy for a panel with only a few components. It can also be incredibly frustrating and difficult for a more complex layout. In most cases, you will want to leave the job to a layout tool.



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net