Part 3: Tips and Techniques


XYLayout is a feature of JBuilder Professional and Enterprise. If you use JBuilder Foundation, substitute null layout wherever XYLayout is specified.

Setting individual constraints in the UI designer

anchor

There are two ways to set a component's anchor constraint in the UI designer:


Note: Moving the component with the mouse updates the anchor constraint value in the GridBagConstraints Editor. Similarly, when you change the constraint value in the GridBagConstraints Editor, the component moves to its new location in the UI designer.


fill

The fastest way to specify the fill constraint for a component is to use the component's pop-up menu in the UI designer.
  1. Right-click the component in the UI designer to display the pop-up menu.
  2. Do one of the following:

You can also specify the fill constraint in the GridBagConstraints Editor.

  1. Right-click the component in the UI designer and choose Constraints to display the GridBagConstraints Editor.
  2. Select the desired constraint value in the Fill area, then press OK.

    Fill


insets

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 zero, you will only see one blue nib on that side of the cell, as shown below.

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.

For more precise control over the Inset values, use the GridBagConstraints Editor to specify the exact number of pixels.

  1. Right-click the component in the UI designer and choose Constraints to display the GridBagConstraints Editor.
  2. In the External insets area, specify the number of pixels for each Inset: Top, Left, Bottom, or Right.

    Insets

Note  Note that while negative Inset values are legal, they can cause components to overlap adjacent components, and are not recommended.


gridwidth, gridheight

You can specify gridwidth and gridheight constraint values in the GridBagConstraints Editor.
  1. Right-click the component in the UI designer and choose Constraints to display the GridBagConstraints Editor.
  2. In the Grid Position area, enter a value for gridwidth in the Width field , or a value for gridheight in the Height field. Specify the number of cells the component will occupy in the row or column.

    Setting gridwidth and gridheight in editor

    Note  Note:  JBuilder never generates a gridwidth or gridheight value of REMAINDER during conversion to GridBagLayout

    You can also use the mouse to change the gridwidth or gridheight by sizing the component into an adjacent empty cells (dragging a black sizing nib across the cell border.)


ipadx, ipady

You can specify a component's Padding (ipadx or ipady) values by clicking on any of the black sizing nibs at the edges of the component, and dragging with the mouse to increase or decrease the size of the component. If you make the component larger than its preferred size, you will see a positive pixel value. If you make the component smaller than its preferred size, you will see a negative pixel value.

If you drag the sizing nib beyond the edge of the cell into an empty adjacent cell, the component will occupy both cells (the gridwidth or gridheight values will increase by one cell).

Before:
Button 1 gridwidth = 1 cell, ipadx = 0

Before dragging the sizing nib

After:
Button 1 gridwidth = 2 cells, ipadx increased to 68)

After dragging the sizing nib into an empty cell

For more precise control over the ipadx and ipady values, use the GridBagConstraints Editor to specify the exact number of pixels to use for the value.

  1. Right-click the component in the UI designer and choose Constraints to display the GridBagConstraints Editor.
  2. In the Size Padding area, specify the number of pixels for the Width and Height values.

    Padding

    Note  Negative values will make the component smaller than its preferred size and are perfectly valid.

To quickly remove the ipadx and ipady constraints (set them to zero), right-click the component in the UI designer and choose Remove Padding. You can also select multiple components and use the same procedure to remove the padding from all of them at once.


gridx, gridy

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 GridBagConstraints Editor.

  1. Right-click the component in the UI designer and choose Constraints to display the GridBagConstraints Editor.
  2. In the Grid Position area, enter the number of columns for the X value, or the number or rows for the Y value. If you want the value to be RELATIVE, enter a -1.

    Setting gridx and gridy in editor

    Note: As you move the component in the UI designer, the gridx (column) and gridy (row) positions are displayed and updated in the status bar at the bottom right. "col:" is gridx and "row:" is gridy. The values in the GridBagConstraints Editor are updated as well.

Note  Important: When you use the mouse to move a component to an occupied cell, the UI designer ensures that two components never overlap by inserting a new row and column of cells so the components will not be on top of each other. When you relocate the component using the GridBagConstraints Editor, the designer does not check to make sure the components don't overlap.


weightx, weighty

If you want your cells to grow, weightx and weighty must be set to a non-zero value.

To specify the weight constraints for a component in the UI designer, right-click the component and choose Weight Horizontal, or Weight Vertical. This sets the value to 1.0.

To remove the weight constraints (set them to zero), right-click the component and choose Remove Weights. You can do this for multiple components in a container: hold down the Shift key when selecting the components, then right-click and choose Remove Weights.

If you want to set the weight constraints to something other than 0.0 or 1.0, you can set the values in the GridBagConstraints Editor.

  1. Right-click the component(s) and choose Constraints to display the GridBagConstraints Editor.
  2. Enter a value between 0.0 and 1.0 for the X or Y value in the Weight area, then press OK.

    weights

Note  Note: weight constraints can sometimes make the sizing behavior in the UI designer difficult to predict, therefore, setting these constraints should be the last step in designing GridBagLayout.

Behavior of weight constraints

Below are some examples of how weight constraints affect a components' behavior:


Using drag and drop to edit constraints

This section of the tutorial contains animations which must be viewed in a JavaScript enabled browser, such as Netscape, or Internet Explorer. A browser version of the JBuilder documentation is available in the JBuilder /doc directory. For directions on viewing the documentation in a browser, see "How to get Help" in Getting Started.

Dragging a component within its display area

When you drag a component in the designer, the outline of the component, and the status bar, indicate what will happen when you let go of the component. For example, from the outline, you can see where a component without fill constraints will anchor in its display area when you release the mouse. And if you are moving a component to a new cell, the status bar indicates which column and row the component will occupy as you move over them, or if a new column or row is needed to accommodate the component.

The status bar also indicates where the component will be placed if you are adding a new component to the GridBagLayout container. However, the fill constraints are set to none when dropping a new component into a cell. Watch the status bar at the bottom right of the animation below as the component is moved.

Also, when you drag a component to a new location in its display area, JBuilder figures out the nearest anchor, then applies the insets necessary to make the component stay where you put it.

Example:  View dragging a component within its display area

Dragging a component to an empty cell

If fill constraints are turned off for the component you're moving, and there are no insets, moving the component to an empty cell automatically adds horizontal and vertical fill constraints to the component. The anchor constraints are determined by where the component is in the display area when you release the mouse. However, until you remove the fill constraints, you won't see the effect of the anchor constraints.

Example:  View animation of moving a button to an empty cell

If both fill constraints are turned off for the component, and insets are specified, moving the component to an empty cell adds both fill constraints and retains the insets.

Example:  View animation of moving component with insets

Dragging a component to an occupied cell

This action gives you the most drastic results when doing drag and drop editing because only one component can occupy a cell. Therefore, if you try to move a component to an occupied cell, GridBagLayout has to make other arrangements for the move. It creates a new column, or a new row for the component.

The side effects of this, however, are that it changes the grid position constraints of many of the other components as well to accommodate the new cells. Their gridx or gridy constraints change if they are after or below the new columns or rows in the grid, and their gridwidth or gridheight may change if the already spanned columns or rows affected by the new ones.

It's especially important to understand this action and resulting behavior, because if you are using the UI designer to build up a new UI from in GridBagLayout (rather than XYLayout), much of the time the grid will be full when you drop a new component onto it, resulting in the creation of new columns or rows, and changing the constraints of existing components.

The example below demonstrates trying to move a button into an adjacent occupied cell, horizontally and then vertically. Watch the right side of the status bar to see how it indicates what column or row you are in, and if a new column or row will be created.

Example:  View animation of moving a button to an occupied cell

Notice the changes GridBagLayout made when Button 3 was dragged into the same cell as Button 1:

Before moving the button

Before moving the button

After moving the button horizontally

Moving button horizontally

And, when it was dragged into the cell above with the checkbox panel:

After moving the button vertically

Moving button vertically

Note You would get the same results if you added a new button to the cell occupied by Button 1 or the checkbox panel, except that no fill constraints would be applied to the new component as is done with a moved component.

Dragging a large component into a small cell

If you drag a large component into a cell that is smaller than the component, the component will span as many empty cells as it needs. Both fill constraints are applied, and insets are still honored. If the component needs more cells than are available (that is, if it runs up against an occupied cell or the edge of the container), then the last cells occupied grow to accommodate the rest of the component, including its insets.

Example:  View animation of dragging a large component into a small cell

Dragging the black sizing nibs

Into an empty cell

Dragging a component's black sizing nib into an adjacent empty cell increases its display area (cell width or height) by one cell in the direction of the move.

Example:  View animation of dragging a component across border of empty cell

Into an occupied cell Dragging a component's black sizing nib into an adjacent occupied cell increases the component's ipadx and ipady constraint values.

Example:  View example of dragging component's sizing nib into an adjacent occupied cell


Adding components

Once you have selected a component from the component palette, as you move your mouse cursor over the area of the grid where you want to add the component, watch the status bar to see what to expect if you drop the component there. The status bar indicates what column and row the component will occupy (its gridx and gridy position), as well as if a new column or row will be created to accommodate the component. You can see this in the animation example below.

When you add a new component to the grid, where you click is important.

The following animation example demonstrates this:

Example:  View animation of adding component to GridBagLayout


Miscellaneous tips

Switch back to XYLayout for major adjustments

If your conversion just didn't give you what you expected, or if you need to add additional components to the design, switch back to XYLayout, make the changes, then re-convert to GridBagLayout. This may be faster and easier than trying to add components to an existing GridBagLayout. Let JBuilder do the work of calculating and assigning the constraints.

Remove weights and fill before making adjustments

Inevitably, at some point in your design work, you will want to make some adjustments to the components in the container once the layout has been changed to GridBagLayout. During the conversion process from XYLayout to GridBagLayout, JBuilder automatically assigns weight constraint values to some of the components.

If you have difficulties as you start moving components or sizing nibs in the UI designer, do an Undo, then remove the weight constraint values from all the components in the GridBagLayout container. weight constraints are the main culprit in causing unexpected behavior when moving and resizing components graphically in a GridBagLayout design. If you remove all weight constraints first, it is easier to make the correct adjustments to the other constraints. (This can also be true of fill constraints. Removing them may make adjustments easier.)

Adjust any other constraints that need modification. When all other constraints are the way you want, then add weight constraints last to only the components that need them.


Making existing GridBagLayout code visually designable

Differences in code

If you create a GridBagLayout container by coding it manually, you typically create only one GridBagConstraints object for the GridBagLayout container and reuse it as you add components to the container. If you want the component you're adding to the container to have different values for particular constraints than the previously added component, then you only need to change those constraint values for use with the new component. These new values stay in effect for subsequent components unless, or until, you change them again.

Note While this method of coding GridBagLayout is the leanest (recycling the GridBagConstraints object from previously added components), it doesn't allow you to edit that container visually in JBuilder's UI designer.

When you design a GridBagLayout container in the UI designer, JBuilder creates a new GridBagConstraints object for each component you add to the container. The GridBagConstraints object has a constructor that takes all eleven properties of GridBagConstraints so the code generated by the UI designer can always follow the same pattern.

public GridBagConstraints(int gridx,
                          int gridy,
                          int gridwidth,
                          int gridheight,
                          double weightx,
                          double weighty,
                          int anchor,
                          int fill,
                          Insets insets,
                          int ipadx,
                          int ipady)
For example,
     jPanel1.add(jButton1, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,GridBagConstraints.CENTER,
          GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
 

Modifying code to work in the UI designer

If you have a GridBagLayout container that was previously coded manually by using one GridBagConstraints object for the container, you must make the following modifications to the code before you can design the container visually in JBuilder:

Code generated by JBuilder in Part 2

Below is the actual code JBuilder generated when we created the GridBagLayout UI in Part 2.
package gbl;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
//import com.borland.jbcl.layout.*;

public class Frame1 extends JFrame {

  //Construct the frame
  BorderLayout borderLayout1 = new BorderLayout();
  JPanel jPanel1 = new JPanel();
  JPanel jPanel2 = new JPanel();
  JLabel jLabel1 = new JLabel();
  JList jList1 = new JList();
  JButton jButton1 = new JButton();
  JCheckBox jCheckBox1 = new JCheckBox();
  JLabel jLabel2 = new JLabel();
  JButton jButton2 = new JButton();
  JPanel jPanel3 = new JPanel();
  JCheckBox jCheckBox2 = new JCheckBox();
  JList jList2 = new JList();
  JPanel jPanel4 = new JPanel();
  JButton jButton3 = new JButton();
  JButton jButton4 = new JButton();
  JButton jButton5 = new JButton();
  GridBagLayout gridBagLayout1 = new GridBagLayout();
  GridBagLayout gridBagLayout2 = new GridBagLayout();
  GridBagLayout gridBagLayout3 = new GridBagLayout();
  GridLayout gridLayout1 = new GridLayout();
  
  public Frame1() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try  {
      jbInit();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
//Component initialization
  
  private void jbInit() throws Exception  {
    this.getContentPane().setLayout(borderLayout1);
    this.setSize(new Dimension(332, 304));
    jPanel2.setBackground(new Color(192, 192, 255));
    jLabel1.setText("Sorted Columns");
    jLabel1.setFont(new Font("Dialog", 0, 11));
    jButton1.setText("Remove from Sort");
    jCheckBox1.setText("Descending");
    jLabel2.setFont(new Font("Dialog", 0, 11));
    jButton2.setText("Add to Sort");
    jPanel3.setBackground(new Color(192, 192, 255));
    jPanel3.setLayout(gridBagLayout3);
    jCheckBox2.setText("Case Sensitive");
    jButton3.setText("Cancel");
    jButton4.setText("Help");
    jButton5.setText("OK");
    gridLayout1.setHgap(6);
    jPanel4.setLayout(gridLayout1);
    jLabel2.setText("Available Columns");
    jPanel2.setLayout(gridBagLayout2);
    jPanel1.setLayout(gridBagLayout1);
    this.setTitle("Frame Title");
    this.getContentPane().add(jPanel1, BorderLayout.CENTER);
    jPanel1.add(jPanel2, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0
            ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 0, 10), 0, 0));
    jPanel2.add(jLabel1, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 2, 0), 0, 4));
    jPanel2.add(jList1, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0
            ,GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 128, 128));
    jPanel2.add(jButton1, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(7, 0, 0, 0), 0, 0));
    jPanel2.add(jCheckBox1, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(6, 0, 0, 0), 0, 0));
    jPanel1.add(jPanel3, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0
            ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 0, 10), 0, 0));
    jPanel3.add(jLabel2, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 2, 0), 0, 4));
    jPanel3.add(jList2, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0
            ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 128, 128));
    jPanel3.add(jButton2, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(7, 0, 0, 0), 32, 0));
    jPanel3.add(jCheckBox2, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(6, 0, 0, 0), 0, 0));
    jPanel1.add(jPanel4, new GridBagConstraints(0, 1, 2, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(12, 59, 12, 59), 0, 0));
    jPanel4.add(jButton5, null);
    jPanel4.add(jButton3, null);
    jPanel4.add(jButton4, null);
  }
//Overridden so we can exit on System Close
  
  protected void processWindowEvent(WindowEvent e) {
    super.processWindowEvent(e);
    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
      System.exit(0);
    }
  }
}

Other resources on GridBagLayout

java.awt.GridBagConstraints.html
java.awt.GridBagLayout.html