Welcome!

Java IoT Authors: Pat Romanski, Roger Strukhoff, Mehdi Daoudi, Liz McMillan, Elizabeth White

Related Topics: Java IoT

Java IoT: Article

SpringLayout: A Powerful & Extensible Layout Manager

SpringLayout: A Powerful & Extensible Layout Manager

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
  • More Stories By 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.

    Comments (4) View Comments

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


    Most Recent Comments
    hubert.gockel 08/17/04 08:10:52 AM EDT

    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.

    Dean Johnston 03/19/03 02:50:00 PM EST

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

    Fred Johnson 12/12/02 02:08:00 PM EST

    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.

    Dave Paules 12/09/02 10:31:00 AM EST

    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).

    @ThingsExpo Stories
    SYS-CON Events announced today that Synametrics Technologies will exhibit at SYS-CON's 22nd International Cloud Expo®, which will take place on June 5-7, 2018, at the Javits Center in New York, NY. Synametrics Technologies is a privately held company based in Plainsboro, New Jersey that has been providing solutions for the developer community since 1997. Based on the success of its initial product offerings such as WinSQL, Xeams, SynaMan and Syncrify, Synametrics continues to create and hone inn...
    Cloud Expo | DXWorld Expo have announced the conference tracks for Cloud Expo 2018. Cloud Expo will be held June 5-7, 2018, at the Javits Center in New York City, and November 6-8, 2018, at the Santa Clara Convention Center, Santa Clara, CA. Digital Transformation (DX) is a major focus with the introduction of DX Expo within the program. Successful transformation requires a laser focus on being data-driven and on using all the tools available that enable transformation if they plan to survive ov...
    A strange thing is happening along the way to the Internet of Things, namely far too many devices to work with and manage. It has become clear that we'll need much higher efficiency user experiences that can allow us to more easily and scalably work with the thousands of devices that will soon be in each of our lives. Enter the conversational interface revolution, combining bots we can literally talk with, gesture to, and even direct with our thoughts, with embedded artificial intelligence, whic...
    To get the most out of their data, successful companies are not focusing on queries and data lakes, they are actively integrating analytics into their operations with a data-first application development approach. Real-time adjustments to improve revenues, reduce costs, or mitigate risk rely on applications that minimize latency on a variety of data sources. In his session at @BigDataExpo, Jack Norris, Senior Vice President, Data and Applications at MapR Technologies, reviewed best practices to ...
    Smart cities have the potential to change our lives at so many levels for citizens: less pollution, reduced parking obstacles, better health, education and more energy savings. Real-time data streaming and the Internet of Things (IoT) possess the power to turn this vision into a reality. However, most organizations today are building their data infrastructure to focus solely on addressing immediate business needs vs. a platform capable of quickly adapting emerging technologies to address future ...
    With tough new regulations coming to Europe on data privacy in May 2018, Calligo will explain why in reality the effect is global and transforms how you consider critical data. EU GDPR fundamentally rewrites the rules for cloud, Big Data and IoT. In his session at 21st Cloud Expo, Adam Ryan, Vice President and General Manager EMEA at Calligo, examined the regulations and provided insight on how it affects technology, challenges the established rules and will usher in new levels of diligence arou...
    In his session at 21st Cloud Expo, Raju Shreewastava, founder of Big Data Trunk, provided a fun and simple way to introduce Machine Leaning to anyone and everyone. He solved a machine learning problem and demonstrated an easy way to be able to do machine learning without even coding. Raju Shreewastava is the founder of Big Data Trunk (www.BigDataTrunk.com), a Big Data Training and consulting firm with offices in the United States. He previously led the data warehouse/business intelligence and B...
    "Digital transformation - what we knew about it in the past has been redefined. Automation is going to play such a huge role in that because the culture, the technology, and the business operations are being shifted now," stated Brian Boeggeman, VP of Alliances & Partnerships at Ayehu, in this SYS-CON.tv interview at 21st Cloud Expo, held Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA.
    "Evatronix provides design services to companies that need to integrate the IoT technology in their products but they don't necessarily have the expertise, knowledge and design team to do so," explained Adam Morawiec, VP of Business Development at Evatronix, in this SYS-CON.tv interview at @ThingsExpo, held Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA.
    The 22nd International Cloud Expo | 1st DXWorld Expo has announced that its Call for Papers is open. Cloud Expo | DXWorld Expo, to be held June 5-7, 2018, at the Javits Center in New York, NY, brings together Cloud Computing, Digital Transformation, Big Data, Internet of Things, DevOps, Machine Learning and WebRTC to one location. With cloud computing driving a higher percentage of enterprise IT budgets every year, it becomes increasingly important to plant your flag in this fast-expanding busin...
    In his Opening Keynote at 21st Cloud Expo, John Considine, General Manager of IBM Cloud Infrastructure, led attendees through the exciting evolution of the cloud. He looked at this major disruption from the perspective of technology, business models, and what this means for enterprises of all sizes. John Considine is General Manager of Cloud Infrastructure Services at IBM. In that role he is responsible for leading IBM’s public cloud infrastructure including strategy, development, and offering m...
    Nordstrom is transforming the way that they do business and the cloud is the key to enabling speed and hyper personalized customer experiences. In his session at 21st Cloud Expo, Ken Schow, VP of Engineering at Nordstrom, discussed some of the key learnings and common pitfalls of large enterprises moving to the cloud. This includes strategies around choosing a cloud provider(s), architecture, and lessons learned. In addition, he covered some of the best practices for structured team migration an...
    No hype cycles or predictions of a gazillion things here. IoT is here. You get it. You know your business and have great ideas for a business transformation strategy. What comes next? Time to make it happen. In his session at @ThingsExpo, Jay Mason, an Associate Partner of Analytics, IoT & Cybersecurity at M&S Consulting, presented a step-by-step plan to develop your technology implementation strategy. He also discussed the evaluation of communication standards and IoT messaging protocols, data...
    Recently, REAN Cloud built a digital concierge for a North Carolina hospital that had observed that most patient call button questions were repetitive. In addition, the paper-based process used to measure patient health metrics was laborious, not in real-time and sometimes error-prone. In their session at 21st Cloud Expo, Sean Finnerty, Executive Director, Practice Lead, Health Care & Life Science at REAN Cloud, and Dr. S.P.T. Krishnan, Principal Architect at REAN Cloud, discussed how they built...
    SYS-CON Events announced today that Evatronix will exhibit at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Evatronix SA offers comprehensive solutions in the design and implementation of electronic systems, in CAD / CAM deployment, and also is a designer and manufacturer of advanced 3D scanners for professional applications.
    22nd International Cloud Expo, taking place June 5-7, 2018, at the Javits Center in New York City, NY, and co-located with the 1st DXWorld Expo will feature technical sessions from a rock star conference faculty and the leading industry players in the world. Cloud computing is now being embraced by a majority of enterprises of all sizes. Yesterday's debate about public vs. private has transformed into the reality of hybrid cloud: a recent survey shows that 74% of enterprises have a hybrid cloud ...
    22nd International Cloud Expo, taking place June 5-7, 2018, at the Javits Center in New York City, NY, and co-located with the 1st DXWorld Expo will feature technical sessions from a rock star conference faculty and the leading industry players in the world. Cloud computing is now being embraced by a majority of enterprises of all sizes. Yesterday's debate about public vs. private has transformed into the reality of hybrid cloud: a recent survey shows that 74% of enterprises have a hybrid cloud ...
    DevOps at Cloud Expo – being held June 5-7, 2018, at the Javits Center in New York, NY – announces that its Call for Papers is open. Born out of proven success in agile development, cloud computing, and process automation, DevOps is a macro trend you cannot afford to miss. From showcase success stories from early adopters and web-scale businesses, DevOps is expanding to organizations of all sizes, including the world's largest enterprises – and delivering real results. Among the proven benefits,...
    @DevOpsSummit at Cloud Expo, taking place June 5-7, 2018, at the Javits Center in New York City, NY, is co-located with 22nd Cloud Expo | 1st DXWorld Expo and will feature technical sessions from a rock star conference faculty and the leading industry players in the world. The widespread success of cloud computing is driving the DevOps revolution in enterprise IT. Now as never before, development teams must communicate and collaborate in a dynamic, 24/7/365 environment. There is no time to wait...
    SYS-CON Events announced today that T-Mobile exhibited at SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. As America's Un-carrier, T-Mobile US, Inc., is redefining the way consumers and businesses buy wireless services through leading product and service innovation. The Company's advanced nationwide 4G LTE network delivers outstanding wireless experiences to 67.4 million customers who are unwilling to compromise on qua...