Skip to main content

Magic with Merlin: SpringLayout manager

When GridBagLayout isn't enough

John Zukowski (jaz@zukowski.net), President, JZ Ventures, Inc.
Author photo
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 jaz@zukowski.net.

Summary:  Many 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.

View more content in this series

Date:  17 Sep 2003
Level:  Introductory
Activity:  1712 views
Comments:  

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


Download

NameSizeDownload method
j-mer09173.zip1KB HTTP

Information about download methods


Resources

About the author

Author photo

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 jaz@zukowski.net.

Comments



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=10869
ArticleTitle=Magic with Merlin: SpringLayout manager
publish-date=09172003
author1-email=jaz@zukowski.net
author1-email-cc=jaloi@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers