The JavaTM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search Feedback Form

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container

## How to Use SpringLayout

> [NOTE: This is an early draft of documentation on `SpringLayout`. We're publishing it before its completion so that you can get examples and a bit of explanation as soon as possible. If you have suggestions for this page, please send us mail.]

> The `SpringLayout` class was added in v 1.4 to support layout in GUI builders. It produces layouts that are similar to absolute positioning, but that react more appropriately to container resizing, changes in text and font, and so on.

> `SpringLayout` can produce many kinds of layouts. Here are pictures of three configurations produced by spring layout:

> The first window, labeled "Form" (and described in Springs in the Form Example), uses a `SpringLayout` to align pairs of items -- in this case, labels with text fields. The second, labeled "Test" (implemented in `Grid.java`), uses a `SpringLayout` to create rows and columns, similar to what a `GridLayout` does. Unlike grid layout, however, this example makes the grid as compact as possible. The third window, labeled "SpringLayout", creates a single-row layout similar to the default layout produced by a `FlowLayout`. It's discussed in the section Example: SpringWindow.

### How Spring Layouts Work

> Spring layouts do their job by defining relationships between the edges of components. For example, you might define that the left edge of one component is a fixed distance (5 pixels, say) from the right edge of another component. By default, a spring layout defines the width and height of a component (the distance between its left and right edges and between its top and bottom edges) to be somewhere between the component's minimum and maximum sizes -- if possible, at its preferred size.

> Distances between edges are represented by `Spring` objects. Each spring has four properties -- its minimum, preferred, and maximum values, and its actual (current) value. The springs associated with each component are collected into a `SpringLayout.Constraints` object.

### Example: SpringWindow

> This section takes you through the typical steps of specifying the constraints for a container that uses `SpringLayout`. The first example, `SpringWindow1.java`, is a modified version of the `FlowWindow` application. . It just creates a `SpringLayout`, sets it as the layout manager for a frame's content pane, and then adds components to the content pane. Here's the relevant code:

> >     public class SpringWindow1 extends JFrame {

> >         public SpringWindow1() {
> >             Container contentPane = getContentPane();
> >             contentPane.setLayout(new SpringLayout());

> >             contentPane.add(new JButton("Button 1"));
> >             contentPane.add(new JButton("2"));
> >             contentPane.add(new JButton("Button 3"));
> >             contentPane.add(new JButton("Long-Named Button 4"));
> >             contentPane.add(new JButton("Button 5"));
> >             ...
> >         }

> >         public static void main(String args[]) {
> >             SpringWindow1 window = new SpringWindow1();
> >             ...
> >             window.pack();
> >             window.setVisible(true);
> >         }
> >     }

> Here's what the GUI looks like when it first comes up:

> Here's what it looks like when it's resized to be bigger:

> Obviously, we have a problem. Not only does the frame come up way too small, but even when it's resized the components all are located at (0,0). This happens because we have set no springs specifying the components' positions and the width of the container. One small consolation is that at least the buttons are at their preferred sizes -- we get that for free from the default springs created by `SpringLayout` for each component.

> Our next example, `SpringWindow2.java`, improves the situation a bit by specifying x and y locations for each component. In this example, we'll specify that all the components appear at their preferred size in a single row. Each component will be exactly 5 pixels away from each other component. The following code specifies the locations (`parent` is the content pane):

> >     Component[] components = parent.getComponents();
> >     SpringLayout layout = (SpringLayout)parent.getLayout();;
> >     Spring xPad = Spring.constant(5);
> >     Spring ySpring = Spring.constant(5);
> >     Spring xSpring = xPad;

> >     // Make every component 5 pixels away from the component to its left.
> >     for (int i = 0; i < components.length; i++) {
> >         SpringLayout.Constraints cons = layout.getConstraints(components[i]);
> >         cons.setX(xSpring);
> >         xSpring = Spring.sum(xPad, cons.getConstraint("East"));
> >         cons.setY(ySpring);
> >     }

> The red lines of code set the springs that determine the x and y coordinates of each component in the container. The y coordinate is always 5. The x coordinate is set so that the components are always 5 pixels apart, horizontally. For example, the first component's origin is at x=5. The second component's x coordinate is 5 + the first component's width. The third component's is at 5 + the first component's width + 5 + the second component's width. And so on. We use the `Spring.sum` method to create a `Spring` that depends on the values of other springs.

> The previous example still has the problem of the container coming up too small:

> But when we resize the window, every component is in its place:

> To make the container the initially appear at the right size, we need to set springs between its right (east) and left edges, and between its bottom (south) and top edges. Here is the code that does this (taken from `SpringWindow3.java`):

> >     Spring maxHeightSpring = Spring.constant(0);
> >     for (int i = 0; i < components.length; i++) {
> >         ...
> >         maxHeightSpring = Spring.max(maxHeightSpring,
> >                                      cons.getConstraint("South"));
> >     //cons is the SpringLayout.Constraints object for components[i]
> >         ...
> >     }

> >     // Make the window's preferred size depend on its components.
> >     SpringLayout.Constraints pCons = layout.getConstraints(parent);
> >     pCons.setConstraint("East", xSpring);
> >     pCons.setConstraint("South", Spring.sum(maxHeightSpring, ySpring));

> Finally, the window comes up at the right size:

### Springs in the Form Example

> The following figure shows the important horizontal springs used in the `Form` application ( `Form.java`). It doesn't show the default springs that control each label's width. Leaving these springs at the default means that each label appears at its preferred width. [PENDING: Explain the figure in more detail.]

> [PENDING: Discuss/show the vertical springs?]

> [PENDING: Discuss the intricacies of working with springs. Discuss proxies vs. original Springs.]

### The SpringLayout API

> The `SpringLayout` class has a single constructor, which takes no argument:

> >     public SpringLayout()

> [PENDING: Discuss the important API for `SpringLayout`, `SpringLayout.Constraints`, and `Spring`.]

### Examples that Use SpringLayout

> The following table lists the examples that use spring layout.

> Example | Where Described | Notes
> --- | --- | ---
> `SpringWindow3` | This page | Uses `SpringLayout` to create a row of evenly spaced, natural-size components.
> `Form` | This page | Uses `SpringLayout` to align labels with text fields.
> `Grid` | This page | Uses `SpringLayout` to create a compact grid.

| Start of Tutorial > Start of Trail > Start of Lesson | Search Feedback Form

Copyright 1995-2001 Sun Microsystems, Inc. All rights reserved.