The i-Technology Media!
Register | Log in
   
 
.NET  ·  AJAX  ·  CLOUD  ·  ECLIPSE  ·  FLEX  ·  OPEN WEB  ·  iPHONE  ·  JAVA  ·  LINUX  ·  OPEN SOURCE  ·  ORACLE  ·  PBDJ  ·  SEARCH  ·  SILVERLIGHT  ·  SOA  ·  VIRTUALIZATION  ·  WEB 2.0  ·  WIRELESS  ·  XML
Comments
Drool, Britannia? Is the UK Failing the Cloud?
By Roger Strukhoff
Richard Davies wrote: The UK has a good crop of technology pioneers in cloud computing - for example ElasticHosts, FlexiScale, Flexiant, OnApp - and also some strong government initiatives such as G-Cloud. We will have to see whether this kind of technical leadership converts into swift mass-market adoption or not.
Jan. 8, 2012 11:38 AM EST
read more & respond »
Cloud Expo on Google News
Did you read today's front page stories & breaking news?

Cloud Expo & Virtualization 2011 West
Keynotes
Oracle
Opening Keynote | An Enterprise Cloud for Business-Critical Applications
Abiquo
Day 2 Keynote | The Enterprise Cloud Tightrope - Balancing for Success
Akamai
Day 3 Keynote | The DNA of an Enterprise Cloud
DIAMOND SPONSOR:
Oracle
Many Clouds, Many Choices'Cloud
PLATINUM PLUS SPONSORS:
Abiquo
Enterprise Cloud Best Practices - Town Hall - Join the discussion…
PLATINUM SPONSORS:
Intel
Progressing Toward the Federated, Automated and Client-Aware Cloud
New Relic
How to build an app with Twitter-like throughput
Rackspace
Computing in the Cloud Era
GOLD SPONSORS:
Gale Technologies
Practical Cloud Migration
IBM
Re-think IT. Re-inventing Business.
Intel/McAfee
Identity Driven Security in the Cloud
PerspecSys
Hackers Hackers Everywhere, Is My Public Cloud That Safe?
Red Hat
Unlock the Value of the Cloud
SHI
Mission Critical Applications and the Cloud - Myth or Reality?
SoftLayer
Not Your Grandpa's Cloud
Terremark
Integrating Enterprise Clouds
VMware
Upgrade to a vCloud
POWER PANELS:
Cloud Expo Silicon Valley: CTO Power Panel
Cloud Expo Silicon Valley: CEO Power Panel
Cloud Expo Silicon Valley: Cloud SuperStars Panel
Cloud Expo Silicon Valley: CloudNOW Panel
Click For 2010 West
Event Webcasts
Cloud Expo & Virtualization 2011 East
DIAMOND SPONSOR:
Dell
Dell & VMware Deliver the Enterprise Hybrid Cloud
PLATINUM PLUS SPONSORS:
Abiquo
Are Financial Services Organizations Risking Security by Avoiding Cloud Computing?
Oracle
From Consolidation to Enterprise Private PaaS
PLATINUM SPONSORS:
Intel
Driving the Transformation to Next Generation Cloud Data Centers
Rackspace
The Inevitability of an Open Cloud
GOLD SPONSORS:
CA Technologies
Follow YOUR path to Cloud Computing
Interxion
Who Keeps the Cloud in the Air?
Microsoft
Patterns for Cloud Computing
PerspecSys
War in the Clouds: Are you ready?
ServiceMesh
The Big Win: Stop Playing Small-Ball with Your Cloud Strategy
Terremark
Evaluating Enterprise Clouds
Xiotech
Cloud Storage: Myths and Realities
POWER PANELS:
Cloud Expo New York: CTO Power Panel
Cloud Expo New York: CEO Power Panel
Cloud Expo New York: CMO Power Panel
Cloud Expo New York: Wrap-Up Power Panel
Click For 2010 West
Event Webcasts
Live Google News by SYS-CON!
Top Three Links You Must Click On


Java SE 6
SpringLayout: A Powerful & Extensible Layout Manager
SpringLayout: A Powerful & Extensible Layout Manager

By: Joe Winchester
Dec. 1, 2002 12:00 AM

The task of a layout manager is to position and size each component based on the size of its container. Each component has a preferred size that can be used to determine the real estate it wishes to occupy, as well as a minimum and maximum size. The preferred size is especially useful for components that contain user-visible strings whose size can change between development and deployment due to different fonts or different locale values, as the GUI is dynamically translated through resource bundles.

Layout managers are powerful classes for dynamically recalculating the size and position of the GUI components at runtime; however, they often lead to a less than optimal design-time experience. With WYSIWYG development tools, it frequently happens that developers position the mouse where they wish to drop a new component, only to see the entire GUI reorganize and the component placed in another location. This is due to the indirection involved in translating the developer's gesture to the correct constraint for the layout manager.

JDK 1.4 introduces a new layout manager - javax.swing.SpringLayout. The motivation behind building it was to create a layout manager that made it easier to design GUIs, was powerful enough to emulate the behavior of all the existing JRE layout managers, and be easily extensible where a new rule was required.

The most pleasant user experience with a design tool occurs when you set the layout manager to null. Then you can place your component exactly where you want it using the mouse and set its size using resize handles. The problem with not having a layout manager is that the explicit bounds of the component are fixed constants set at design time. With SpringLayout you can specify each component's x, y, width, and height, but instead of using fixed coordinates, the constraints are springs. These springs can be derived from the edges of existing components, and are able to flex under tension and compression when the window size is changed.

To illustrate SpringLayout this article demonstrates how to use springs to anchor edges of components and align widths, and how to create complex springs.

Background
To specify how each component should be positioned and sized by the layout manager you must use a constraint object, which is an instance of the inner class javax.swing.SpringLayout.Constraints. A SpringLayout.Constraints object contains six springs - for the component's width and height and each of its four edges.

A spring is analogous to a physical spring that connects the edge of the component to another point on the GUI. Each edge is controlled by a single spring, so springs are best thought of as directional. For example, a spring that fixes the left edge of a component to the right edge of another doesn't operate in reverse. When the first component's right edge moves, this affects the second component's left edge, but not vice versa.

Springs can be fixed struts that have a constant value, or else can be flexed under tension and compression. To determine how elastic a spring is, it has a preferred, minimum, and maximum value. If the minimum value is the same as the preferred value, the spring is rigid under compression, and, likewise, if the maximum value is the same as its preferred value the spring can't be expanded. If no spring is specified for a component's width or height, the default spring created defers its preferred minimum and maximum values to the component. In addition to using individual springs to anchor and size components, springs can be combined to create compound springs whose elasticity is the sum, maximum or minimum, of its arguments.

When designing a GUI using SpringLayout, draw a diagram of the components in the positions you want them to be in, and then mentally determine what will keep them in those positions. Usually this will be a fixed length spring between the component's left and top edge relative to its nearest neighbor's edges. This is very useful for components that contain user-visible strings, such as buttons and labels where the exact size isn't known until runtime, because the font used or the actual string, if it has been externalized in a locale-specific bundle, can vary.

To show how to use springs, this article builds a simple GUI that illustrates some of the common types. The screen images have red lines drawn on them to help you visualize each spring. This approach, drawing springs between components, is an intuitive way to design a GUI where you begin by drawing the components at their absolute positions and sizes and then add lines to represent the springs. A GUI builder could employ this method where you drop a control at the position you want it placed, and springs are automatically created between it and its nearest neighbors.

Constant Springs
The simplest spring is a fixed value that positions an edge a constant distance from its parent container. Figure 1 shows a button that has two constant springs used to position it at 5,10 inside a frame's contentPane. The SpringLayout class automatically generates a Constraints object for every component that's added to its container, so in order to change any of the springs you can query the Constraints object and set new values. To create a constant fixed spring, use the static method Spring.constant(int).

JButton okButton = new JButton("OK");
contentPane.add(okButton);
SpringLayout.Constraints okCst =
layout.getConstraints(okButton);
okCst.setX(Spring.constant(10));
okCst.setY(Spring.constant(5));

Springs Between Edges
In Figure 1 the springs for the OK button were fixed lengths of 5 and 10. Even though no springs were specified for the width and height of the button, some were created automatically based on the preferred, minimum, and maximum size. These springs can be queried and used in the constraints of other components so you can position them relative to each other. For example, a Cancel button can be added to the content pane, whose x spring is the right-edge spring of the OK button. To query the spring for an edge, the method public Spring getConstraint(String edgeName) can be used that takes arguments of "North", "East", "South", and "West" for each edge. To position the Cancel button so its left edge is a fixed distance away from the right edge of the OK button, a compound spring is used. The method Spring.sum(Spring spring1,Spring spring) creates a compound spring whose value is the sum of two arguments. By combining the east edge of the OK button with a constant spring of 5, a spring is created that will always be five larger than the right edge of the OK button. This spring is then used as the x spring of the Cancel button.

JButton cButton = new JButton("Cancel");
contentPane.add(cButton);
SpringLayout.Constraints cCst =
layout.getConstraints(cButton);
cCst.setY(Spring.constant(5));
cCst.setX(Spring.sum(
Spring.constant(5),
okCst.getConstraint("East")));

The result of this is shown in Figure 2 where the Cancel button is positioned to the right of the OK button with a space of 5 pixels in between.

Sizing the Window with Springs
In addition to allowing you to specify constraints for a container's components, you can specify a constraint for the container that allows you to control its edges. The content pane's right edge can be set with a compound spring as 20 away from the right edge of the cancel button. To do this, retrieve the spring for the layout manager's container, and then set its east spring.

SpringLayout.Constraints pnlCst =
layout.getConstraints(contentPane);
pnlCst.setConstraint("East",Spring.sum(
Spring.constant(20),
cCst.getConstraint("East")));

For the content pane's bottom edge a spring can be put between it and the bottom of the buttons. This spring can make the bottom of the contentPane be a distance of 15 away from the buttons, and because the OK and Cancel buttons are the same height and have the same y spring, the content pane's bottom edge can spring from either one. A compound sum spring is created that adds the south spring of the cancel button's constraint to a fixed spring of 15.

pnlCst.setConstraint("South",Spring.sum(
Spring.constant(15),
cancelCst.getConstraint("South")));

When there are springs controlling the edges of the contentPane, the window can be packed to give it an initial size (see Figure 3). In the previous examples where there were no springs for the edges of the contentPane, the window was given a fixed size of 200 by 200.

The content pane's edges can have a spring between them and a specific control, such as the Cancel button. However, if there is no single control that determines the edges of the content pane, a compound spring can be created. This compound spring needs to determine which is greater, the south spring of the OK button or the Cancel button. The method Spring.max(Spring spring1, Spring spring2) is used to create a single spring whose value is the greater of the two arguments.

pnlCst.setConstraint("South",
Spring.sum(Spring.constant(15),
Spring.max(
cancelCst.getConstraint("South")),
okCst.getConstraint("South")));

Springs for Widths and Heights
You can also use springs to set a component's size, as well as its position. For example, instead of the OK and Cancel button each being their preferred size, you want them to be the same size. The size used will need to be the larger of each button's preferred size so that neither label is clipped and a compound spring can be created based on the maximum of the two widths.

Spring widthSpring = Spring.max(
okCst.getWidth(),
cancelCst.getWidth());
okCst.setWidth(widthSpring);
cancelCst.setWidth(widthSpring);

Because the code changes the spring that specifies the width of the OK button, and this spring is also used to calculate the distance between the OK and Cancel buttons, the constraint between the two buttons must be defined after setting their width springs. This ensures that the x spring of the cancel constraint is not based on its original width spring, but is derived from the max spring instead. The order of setting springs that form input to compound springs is important, and the following code must be done after the OK button's width spring is set.

cancelCst.setX(Spring.sum(
Spring.constant(5),
okCst.getConstraint("East")));

Likewise the spring that's created between the content pane's right edge and the right edge of the Cancel button must be defined after the width spring is established. Generally, it's a good idea to specify any explicit width or height springs before defining the positional springs between components to ensure that no queried width or height springs are later replaced. Because the word "Cancel" is longer than "OK", the OK button's width is increased to match that of the Cancel button. However, if in a different language the lengths were reversed, the two buttons would always remain the same width. Figure 4 shows that the OK and Cancel buttons are the same size, and that the overall window size still remains 20 and 15 away from the Cancel button.

The ability to compute a component's width and height using a compound spring gives you a level of control not previously possible with other layout managers. In GridBagLayout you can align widths of components by placing them in the same column, but with SpringLayout you can align widths where the controls are side by side as shown in Figure 4. Sometimes the requirement for laying out buttons may be a rule such as "Make the buttons have the same width but make this be no smaller than 60." This can be created by having a compound spring such as:

Spring widthSpring = Spring.max(
Spring.constant(60),
Spring.max(
okCst.getWidth(),
cancelCst.getWidth()));

Components Resizing with the Container
For some components, such as JTextArea, the desired layout is to make as much use of the available space as possible. To do this springs can be made between the east and south edge of the text area and its container. Listing 1 creates a JTextArea and adds constant springs between its east edge and the container, and its south edge and the container. The lines of code setting the springs between the Cancel button can be deleted as the contentPane's constraints are attached to the text area; although, if left there the panel will use the newest springs since only one spring can be held for each constraint in the SpringLayout.Constraint class, and setting a new one replaces any existing spring.

The panel opens with a default size based on the preferred size of the JTextArea (see Figure 5).

When the panel is resized, the JTextArea will be resized with it, expanding to make use of extra width or height. This occurs with the JTextArea and not with the OK and Cancel buttons due to the default width and height springs that were initially created for each component by the layout manager. A JButton's preferred, minimum, and maximum sizes are all the same value, so there is no "give" in an arrangement of buttons connected together with "struts." By contrast, a JTextArea's minimum and maximum and size are not the same, so the default width and height springs can expand and compress. After the panel changes size, the layout manager looks at the flexibility of all its springs and, based on their elasticity, calculates their values.

The JTextArea becomes larger when the window size is expanded, and smaller when the size is reduced. The fixed-edge springs remain at their value of 10, while the JTextArea shrinks to occupy the remaining space.

With a reduced window size the springs between the edges of the JTextArea and its neighboring edges remain 10 pixels wide, and the JTextArea reduces in size because its minimum size that provides the input to its width and height springs is 0 (see Figure 6). However, rather than have the springs between the JTextArea and its neighbors rigid, they can be made flexible so they'll compress when the window size is reduced. This way, when the window is made smaller, more of the actual space can be given to the JTextArea.

In addition to defining a single value for a constant spring, you can also set a minimum and maximum size, e.g., Spring.constant(0,10,20). If the minimum and maximum values are the same as the preferred value, which occurs when the single argument constructor is used, the spring becomes an inflexible strut. However, with a minimum and maximum size, when the window size is changed, the layout manager takes these values into account to determine the new actual values of each spring. To illustrate this all the springs used in the example between the JTextArea and its neighbors were set to be constant with a minimum of 0, a maximum of 20, and a preferred size of 10.

txtCst.setY(Spring.sum(
Spring.constant(0,10,20),Spring.max(
cancelCst.getConstraint("South"),
okCst.getConstraint("South"))));
pnlCst.setConstraint("East",
Spring.sum(Spring.constant(0,10,20),
txtCst.getConstraint("East")));
pnlCst.setConstraint("South",Spring.sum(
Spring.constant(0,10,20),
txtCst.getConstraint("South")));

What occurs now is that when the window is reduced in size, the springs can be compressed. The layout manager looks at the compressibility of each spring, including the implicit spring that the JTextArea has for its width and height, to determine the size and position of the controls. When the window is made smaller, the springs compress and the JTextArea occupies more of the available real estate. When the window size was reduced to a height of 77, the JTextArea, with rigid springs around it, was made 26 high, enough to show two lines of text. However, the flexible springs mean that they can take the strain and allow the JTextArea to have a larger size (see Figure 7). The top and bottom Springs are compressed to a value of 4, and the JTextArea has 12 extra pixels available for its height, making it 28 high so it can display an extra row of text. If flexible springs were also used for the top of the two buttons, the window could be further optimized so that yet more of the more available space was allocated to the JTextArea under compression.

The rules by which the layout manager determines how much to compress each of the springs are based on how much it resists being compressed. When a spring is compressed, imagine that it provides an opposite force that increases as it reaches its minimum value. If the minimum and preferred values are the same, the force is an irresistible one and the spring is rigid.

The springs between the edges have a minimum value of 0 and a preferred of 10, and the JTextArea's height spring is based on its minimumSize's height of 0 and preferredSize's height of 5 rows of characters at the current font. Both of these springs are compressed as the window size decreases. When the window is increased, the edge springs have a maximum size of 20 and a preferred size of 10, however, the maximumSize of the JTextArea is based on the look and feel but is likely to be Integer.MAX_VALUE. Because the resistance of a spring increases as its value approaches its maximum value, for the JTextArea's width or height to become rigid the window would have to become enormous. Use of compressible springs between components allows you to create a GUI that reallocates its available spaces across its components as it changes size, so the user has more available working component area and the window remains effective over a longer range of overall sizes.

Convenience Methods for Attaching Springs Between Edges
To attach the Cancel button to the OK button and make them 5 apart:

cancelCst.setX(Spring.sum(
Spring.constant(5),
okCst.getConstraint("East")));

This scenario, where you attach the edge of one component a fixed distance from another, occurs frequently when creating GUIs with SpringLayout, so there's a helper method

SpringLayout.putConstraint(String targetEdge,
Component targetComponent, int distance,
String sourceEdge, Component sourceComponent);
layoutManager.putConstraint("East",
cancelButton , 5, "East", okButton);

Creating Springs in the Correct Order
Because of the cyclic nature of springs, i.e., they are often calculated based on existing springs that are combined to create new compound springs, the order in which the constraints are set is important. For example, if you query the west or width spring of a component, should you then set its east spring, afterward this could affect either of the previously queried springs, making their values stale. Therefore, it's important to establish and query strings in the correct order. The analogy is that of a spreadsheet whose cells' values are based on calculations that include other cells' values as input.

An application window is made up of a set of components, and SpringLayout lets you add a set of springs into this picture. The springs define the positions and sizes of components, and can be anchored to other components' edges, or can be derived from calculations using existing springs.

We hope that you'll have some fun with SpringLayout and that it helps solve some of those difficult layout problems where things don't work out quite the way you want. In our minds at least, the holy grail of layout experiences would be a GUI builder that would allow the user to add constraints between components visually - rather than having to write code. This is quite a difficult problem; if you're working on a GUI builder or have ideas about the best way to do this - drop us a line!

Resources

  • Online tutorial of SpringLayout: http://java.sun.com/docs/books/ tutorial/uiswing/layout/spring.html
  • JDK 1.4 SDK download: http://java.sun.com/j2se/1.4/download.html
    Published Dec. 1, 2002— Reads 34,143 — Feedback 4
    Copyright © 2002 SYS-CON Media, Inc. — All Rights Reserved.
    Syndicated stories and blog feeds, all rights reserved by the author.
    Related Links
    ▪ Figure 1
    ▪ Figure 2
    ▪ Figure 3
    ▪ Figure 4
    ▪ Figure 5
    ▪ Figure 6
    ▪ Figure 7
    ▪ Source Code
    About Joe Winchester
    Joe Winchester, Editor-in-Chief of Java Developer's Journal, was formerly JDJ's longtime Desktop Technologies Editor and is a software developer working on development tools for IBM in Hursley, UK.

  • Add Your Feedback

    In order to post a comment you need to be registered and logged in.

    Register | Sign-in

    Reader Feedback: Page 1 of 1

    #4
    hubert.gockel commented on 17 Aug 2004

    Excellent! Was trying hard to to come across all the mysteries of this new layout management technique but did not succeed prior to studying this fine article.

    #3
    Dean Johnston commented on 19 Mar 2003

    And before OS/2, Motif did it. Nice to see Smalltalk and something to learn as well.

    #2
    Fred Johnson commented on 12 Dec 2002

    IBM's VisualAge Smalltalk implemented the same flexibility back in the days of OS/2, only they called it "anchoring" and tended to specify the connections as pixels or percentages. Of course, their GUI builder also generated executable code for events and messages, not just a blank form. In many areas, Smalltalk achieved years ago what is now considered leading edge in Java.

    #1
    Dave Paules commented on 9 Dec 2002

    This is a great way to build GUIs. The Mac folks have been building UIs with springs with Apple's Interface Builder. It's great to be able to visualize what will happen to a UI BEFORE it is run. I'm glad to see that Sun is imitating best practices like this in the industry. Let's hope that Apple will push swing even further (directly or indirectly).


    Subscribe to the World's Most Powerful Newsletters
    Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
    Click to Add our RSS Feeds to the Service of Your Choice:
    Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
    myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
    Publish Your Article! Please send it to editorial(at)sys-con.com!

    Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021

    SYS-CON Featured Whitepapers

    ADS BY GOOGLE

    Breaking Java News
    First Resource Bank Announces New Executive Vice President & Chief Operating Officer Jeffrey D. Barton
    Fauquier Bankshares, Inc. Declares Quarterly Dividend; Sets Annual Shareholder Meeting
    Critical Alerts for American Express, Western Digital, Johnson Controls, Advance Auto Parts, and Goldcorp Released by Seven Summits Research
    Critical Alerts for IBM, DirecTV, Ultra Petroleum, Hospira, and PACCAR Released by Seven Summits Research
    3net and Partners Discovery, Sony and IMAX Release Definitive Guide to 3D Television Production
    Collateral Intelligence to Support FICO Analytics That Predict Strategic Mortgage Defaults
    Anton/Bauer to Unveil Groundbreaking Swappable Power Systems at HIMSS12
    Adapt Claims Spotlight as One of America’s Fastest Growing Unified Communications Resellers and Systems Integrators
    Discovery Channel's Daily Planet to Visit Tucson to Film Segment on Kryron Technology
    ABF Recognized With a Top 10 Listing on the Training Top 125

    ADVERTISE   |   MAGAZINE SUBSCRIPTIONS   |   FREE BREAKING-NEWSLETTERS!   |   SYS-CON.TV   |   BLOG-N-PLAY!   |   WEBCAST   |   EDUCATION   |   RESEARCH

    .NET Developer's Journal - .NETDJ   |   ColdFusion Developer's Journal - CFDJ   |   Eclipse Developer's Journal - EDJ   |   Enterprise Open Source Magazine - EOS
    Open Web Developer's Journal - OPENWEB   |   iPhone Developer's Journal - iPHONE   |   Virtualization - Virtualization   |   Java Developer's Journal - JDJ   |   Linux.SYS-CON.com
    PowerBuilder Developer's Journal - PBDJ   |   SEO / SEM Journal - SJ   |   SOAWorld Magazine - SOAWM   |   IT Solutions Guide - ITSG   |   Symbian Developer's Journal - SDJ
    WebLogic Developer's Journal - WLDJ   |   WebSphere Journal - WJ   |   Wireless Business & Technology - WBT   |   XML-Journal - XMLJ   |   Internet Video - iTV
    Flex Developer's Journal - Flex   |   AJAXWorld Magazine - AWM   |   Silverlight Developer's Journal - SLDJ   |   PHP.SYS-CON.com   |   Web 2.0 Journal - WEB2
    Apache   |   CMS   |   CRM   |   HP   |   Oracle Journal   |   Perl   |   Python   |   Red Hat   |   Ruby on Rails   |   SAP   |   SaaS

    SYS-CON MEDIA:   ABOUT US   |   CONTACT US   |   COMPANY NEWS   |   CAREERS   |   SITE MAP
    SYS-CON EVENTS:   |  AJAXWorld Conference & Expo  |  iPhone Developer Summit  |  Cloud Computing Conference & Expo  |  SOA World Conference & Expo  |  Virtualization Conference & Expo
    INTERNATIONAL SITES:   India  |  U.K.  |  Canada  |  Germany  |  France  |  Australia  |  Italy  |  Spain  |  Netherlands  |  Brazil  |  Belgium
     Terms of Use & Our Privacy Statement     About Newsfeeds / Video Feeds
    Copyright ©1994-2008 SYS-CON Publications, Inc. All Rights Reserved. All marks are trademarks of SYS-CON Media.
    Reproduction in whole or in part in any form or medium without express written permission of SYS-CON Publications, Inc. is prohibited.
     
    close this window