IBM Skip to main content
Search for:   within 
      Search help  
     IBM home  |  Products & services  |  Support & downloads   |  My account

developerWorks > Java technology
developerWorks
Magic with Merlin: SpringLayout manager
Discusscodee-mail it!
Contents:
Getting started with SpringLayout
Using putConstraint() with SpringLayout
Trying out SpringLayout with BeanBuilder
Complete SpringLayout example
Resources
About the author
Rate this article
Related content:
Build a better GUI
Developing accessible GUIs with Swing
Magic with Merlin series
Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)
When GridBagLayout isn't enough

Level: Introductory

John Zukowski (mailto:jaz@zukowski.net?cc=&subject=SpringLayout manager)
President, JZ Ventures, Inc.
17 September 2003

Column iconMany developers try to avoid the powerful GridBagLayout manager when designing complex screens. Instead of fiddling with the GridBagConstraints, they embed panels inside panels with different layout managers like BorderLayout. The newly introduced SpringLayout manager offers an alternative in which components are positioned relative to one another. In this article, Merlin veteran John Zukowski shows you how to use this new layout manager. Share your thoughts on this article with the author and other readers in the accompanying discussion forum. (You can also click Discuss at the top or bottom of the article to access the forum.)

The newest addition on the Java layout manager front is the SpringLayout manager, added with the Java 1.4 release. This layout manager allows you to attach "springs" to components so that they can be laid out relative to other components. For instance, with SpringLayout, you can say that a button appears attached to the right border, no matter what size a user makes the screen.

Getting started with SpringLayout
Like all layout managers, the SpringLayout manager is responsible for positioning components. Component positions are controlled by associating constraints to them. For SpringLayout-controlled components, there is one constraint with four settings -- one for each edge of the component. The SpringLayout manager relies on a SpringLayout.Constraints object for these component constraints. This works similar to the GridBagConstraints class that complements the GridBagLayout manager: Each component added to the container can have an attached SpringLayout.Constraints object. This, however, is where the similarities end.

While with GridBagLayout, you typically add the component to the container with the constraints, in the case of the SpringLayout manager, you usually don't have to add the component with the constraints. Instead, you can add the component and then attach the constraints separately. There is nothing stopping you from adding the constraints with the component, but SpringLayout.Constraints is not a simple class. It is a collection of Spring objects (for each edge), each being a different constraint on the component. When you use it, you need to add each Spring constraint separately to SpringLayout.Constraints. You "add" constraints to SpringLayout.Constraints by setting specific constraints on an edge of the component. Using the four SpringLayout constants of EAST, WEST, NORTH, and SOUTH, you call the setContraints(String edge, Spring spring) method of SpringLayout.Constraints, where String is one of the constants. For instance, if you wanted to add a component in the top-left of a container, you could set up two springs of constant size, combine them together, and add the component to the container with the combined set, as shown here in Listing 1:

Listing 1. Working with SpringLayout

Component left = ...;
SpringLayout layout = new SpringLayout();
JPanel panel = new JPanel(layout);
Spring xPad = Spring.constant(5);
Spring yPad = Spring.constant(25);
SpringLayout.Constraints constraint = new SpringLayout.Constraints();
constraint.setConstraint(SpringLayout.WEST, xPad);
constraint.setConstraint(SpringLayout.NORTH, yPad);
contentPane.add(left, constraint);

That may not look particularly difficult, but it gets harder when you need to add the next component, either to the right of the first or below it. You can't just add the component n pixels over; you actually must add the padding to the edge of the earlier component. To find the edge of the earlier component, you ask the layout manager with getConstraint(), passing in the edge you want and the component, as in layout.getConstraint(SpringLayout.EAST, left), to get the location of the right edge of the first component. From that, you can add in the necessary padding and attach it to the edge of the other component, as shown in Listing 2:

Listing 2. Adding the second component with SpringLayout

Component right = ...;
Spring rightSideOfLeft = layout.getConstraint(SpringLayout.EAST, left);
Spring pad = Spring.constant(20);
Spring leftEdgeOfRight = Spring.sum(rightSideOfLeft, pad);
constraint = new SpringLayout.Constraints();
constraint.setConstraint(SpringLayout.WEST, leftEdgeOfRight);
constraint.setConstraint(SpringLayout.NORTH, yPad);
contentPane.add(right, constraint);

Using putConstraint() with SpringLayout
This approach works perfectly well, but gets tedious as the number of components increases. Instead, another way that sidesteps the in-between steps is to add the components without the constraints and then add each separately, using the putConstraint() method of SpringLayout to connect the components, as shown in Listing 3:

Listing 3. Adding the second component with SpringLayout

public void putConstraint(String e1, Component c1, int pad, 
  String e2, Component c2)
public void putConstraint(String e1, Component c1, Spring s, 
  String e2, Component c2)

Here, instead of asking for the edge and adding in the padding yourself, the putConstraint() call combines the tasks for you. To demonstrate, Listing 4 adds the same component constraints to the right component as Listing 3, but uses putConstraint() instead of SpringLayout.Constraints directly:

Listing 4. Using putConstraint() to add the second component

Component left = ...;
Component right = ...;
SpringLayout layout = new SpringLayout();
JPanel panel = new JPanel(layout);
panel.add(left);
panel.add(right);
layout.putConstraint(SpringLayout.WEST, left, 5, 
  SpringLayout.WEST, panel);
layout.putConstraint(SpringLayout.NORTH, left, 25, 
  SpringLayout.NORTH, panel);
layout.putConstraint(SpringLayout.NORTH, right, 25, 
  SpringLayout.NORTH, panel);
layout.putConstraint(SpringLayout.WEST, right, 20, 
  SpringLayout.EAST, left);

The String arguments of putConstraint() are the four SpringLayout constants EAST, WEST, NORTH, and SOUTH. When you use putConstraint(), be sure to specify the unknown component position first and connect it to something that can be calculated or is fixed, like the edge of the screen.

Trying out SpringLayout with BeanBuilder
To help you visualize the use of SpringLayout, Sun has a tool available called BeanBuilder (see Resources). The tool is meant more to be used when working with JavaBeans components, but it also offers an easy way to explore SpringLayout. Figure 1 shows what the tool looks like on startup:

Figure 1. BeanBuilder startup screen
 BeanBuilder Startup Screen

While we're not going to talk about the specifics of the tool, one thing BeanBuilder does let you do is connect components with SpringLayout. Around the edges of each component are a set of four boxes, one each for north, south, east, and west. You can drag an arrow out of a box and connect it to any other box. If the tool were a little more sophisticated, it would permit you to specify gap sizes, but Figure 2 shows what a screen might look like during development:

Figure 2. BeanBuilder usage screen
 BeanBuilder Usage Screen

As Figure 2 illustrates, you can visually connect the arrow to a specific putConstraint() call.

Complete SpringLayout example
To demonstrate the use of SpringLayout, Listing 4 is the SpringFormTest program that connects the pieces explained using putConstraint(). (You can also download this code; see Resources.)

Listing 4. Complete SpringLayout example

import java.awt.*;
import javax.swing.*;
public class SpringFormTest {
  public static void main(String args[]) {
    JFrame frame = new JFrame("Spring Form");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container contentPane = frame.getContentPane();

    SpringLayout layout = new SpringLayout();
    contentPane.setLayout(layout);

    Component left = new JLabel("Left");
    Component right = new JTextField(15);

    contentPane.add(left);
    contentPane.add(right);

    layout.putConstraint(SpringLayout.WEST,  left, 10,
      SpringLayout.WEST,  contentPane);
    layout.putConstraint(SpringLayout.NORTH, left, 25,
      SpringLayout.NORTH, contentPane);
    layout.putConstraint(SpringLayout.NORTH, right, 25,
      SpringLayout.NORTH, contentPane);
    layout.putConstraint(SpringLayout.WEST, right, 20,
      SpringLayout.EAST, left);

    frame.setSize(300, 100);
    frame.show();
  }
}

Figure 3 shows the results:

Figure 3. SpringFormTest example screen
 SpringFormTest Example Screen

Resources

About the author
John Zukowski conducts strategic Java consulting with JZ Ventures, Inc., offers technical support through AnswerSquad.com, and is working with SavaJe Technologies to develop a next-generation mobile phone platform. His latest books are Mastering Java 2, J2SE 1.4 (Sybex, April 2002) and Learn Java with JBuilder 6 (Apress, March 2002). Contact John at mailto:jaz@zukowski.net?Subject=Magic with Merlin.


Discusscodee-mail it!

What do you think of this document?
Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Send us your comments or click Discuss to share your comments with others.



developerWorks > Java technology
developerWorks
  About IBM  |  Privacy  |  Terms of use  |  Contact