Eclipse vs. Swing
Awareness of toolkit trade-offs can help you decide which Java GUI is the right one for your application
by Daniel F. Savarese
I've never been a fan of integrated development environments (IDEs), but there's no doubt that many programmers find them useful. Even though I do not use IDEs on a daily basis, I make a point of keeping up with the latest product offerings. You've got to keep an open mind in the software business, and I'm not going to avoid using a tool that will make me more productive.
Eclipse, one of the more recent Java IDEs, has been creating quite a stir. Not only is it open source software—distributed under the Common Public License—backed by an impressive consortium of companies, including IBM and Borland, but also, despite being implemented in Java, it does not use a single line of Abstract Window Toolkit (AWT) or Swing code. Rather than ask why the members of the Eclipse Consortium, noticeably missing representation from Sun Microsystems, decided to jointly develop an IDE when many of its members already had IDE products, I want to discuss the Eclipse GUI implementation decision that has rekindled the debate over how best to implement cross-platform user interfaces in Java.
Eclipse is not just a Java IDE. To borrow the words of its creators, "Eclipse is an open platform for tool integration." It is implemented in Java but not restricted to Java development tasks. Much like Microsoft's Visual Studio, Eclipse allows you to write your own tools that integrate with the IDE. In this way, Eclipse can be extended for any software development purpose. The unit of extension is called a plug-in. The componentization of Eclipse is so great that virtually every unit of functionality is implemented as a plug-in. In fact, many plug-ins can be plugged out, so to speak, and used independently. This was the approach used to implement the Standard Widget Toolkit (SWT), which forms the basis of user interface development for plug-ins. You can write Java applications that use SWT to implement their GUIs without requiring the Eclipse IDE to host them.
SWT is a basic graphics and widget toolkit for Java. It has no dependencies on graphics code from the Java core APIs. Eclipse also provides an additional toolkit, called JFace, that builds on top of SWT, providing more complex widgets and high-level functionality such as image and font registries. Together, SWT and JFace replicate the functionality provided by Swing and a subset of the Java Foundation Classes. It is significant that a consortium of companies with large financial stakes in the success of Java would opt to design their own cross-platform GUI toolkit to implement a substantial application rather than use the one provided as a standard part of the Java platform. Also significant is that some Java developers are adopting this toolkit in lieu of Swing to build their applications. Let's see why you might consider following suit.
Getting into the Swing
There is no right way to approach the development of a cross-platform GUI development. There are only a series of trade-offs with different ramifications that you may or may not be able to live with. Java's original AWT package took a least-common-denominator approach. It implemented GUI components available only on all of its target platforms. It also relied on native widgets to implement user interfaces. The result was a framework with restricted functionality that produced GUIs that looked different and behaved differently on every operating system.
Swing opted to take full control by using lightweight components. All component rendering and event processing was handled in Java. A consistent look could be achieved across operating systems or native looks could be emulated. Performance was sacrificed in the process, giving Swing interfaces a sluggish feel. Native widget appearance and behavior could never be duplicated exactly, yielding occasional surprises.
SWT takes an approach akin to AWT with elements of Swing. SWT uses native widgets except when a class of widget is not commonly available on all target platforms. In that case, SWT emulates the widget on platforms that do not support it natively. Useful platform-specific features, such as ActiveX control integration, are supported, but rarely used features are omitted.
The advantage of the SWT approach is that GUIs look and feel exactly like native GUIs. When Windows XP was released with a new look, Swing had no XP look and feel, but SWT automatically picked it up. Other advantages are that graphics performance is close to native, and platform-specific features, such as embedding ActiveX controls and using native drag-and-drop, can be accessed if desired. Disadvantages are that SWT does not support pluggable look and feels and that the door is opened to write nonportable code (yes, I also listed this as an advantage for it is both). Eclipse's designers obviously felt that the trade-offs made by Swing were unfavorable for implementing their idea of what an IDE should be. As a result, they've created a library that you can use for your own applications should you have a similar set of requirements.
To show the differences between Swing and SWT, I have written the same program twice, once with Swing and once with SWT. The program exercises just enough graphics to demonstrate fundamental differences in the respective APIs, the appearance of the resulting program, and even performance. The first version of the program using Swing loads two images and uses them to create a checkerboard inside of a scrollable area (see Listing 1). A combo box selection changes the dimensions of the checkerboard and redraws the application window.
Checkers Anyone?
The checkerboard is drawn by BoardPanel, which overrides the Component.paint() method. ImageIcon instances load and store the checkerboard square images. Otherwise, you'd have to get a reference to the default AWT Toolkit object, invoke its createImage() method, and use a MediaTracker object to wait until the image finishes loading. That's quite a lot of work to go through when all you want to do is load some graphics into memory, so it's better to let the ImageIcon class take care of it. SizeListener implements the ItemListener interface and receives selection events from the JComboBox and resizes the checkerboard appropriately. The resulting application is shown in Figure 1, sporting the default Java look and feel.
You will need to download Eclipse and put its swt.jar and swt-pi.jar files in your classpath to compile and run the SWT version of the same program (see Listing 2). Furthermore, you will need to put the shared library with the native windowing code where your Java run-time environment can find it. I just left the library in its default directory relative to my Eclipse installation directory and defined the java.library.path property on the command line as follows:
java -Djava.library.path=
/net/opt/eclipse/
eclipse-2.0.1/plugins/
org.eclipse.swt.gtk_2.0.1/
os/linux/x86 example.SWTBoard
Like Swing, SWT is divided into a good number of packages. The most important packages are used by the code you see in Listing 2. The swt package contains the SWT class, which stores many of the constants used by the other packages. The graphics package contains all of the classes related to drawing and image display, such as the GC graphics context class and Image. The widgets package contains basic widgets such as Button, and the custom package contains more complex widgets such as ScrolledComposite. The layouts package contains classes for laying out components inside of a container, called a Composite in SWT. Finally, the events package contains event-handling classes.
The structure of SWT parallels that of Swing in some ways but, overall, is fundamentally different. All Swing graphics components are garbage collected. Once you allocate a resource, you don't have to dispose of it. In SWT, you have to dispose of every resource you allocate. Resources you do not explicitly allocate will be disposed of by the code that originally allocated them. The only exception is that parent components dispose of their children. Notice that BoardCanvas allocates two Image instances and takes care to register a DisposeListener to dipose of them when a parent disposes of the BoardCanvas (see Listing 2). This use of an event listener highlights another important difference. All actions are consistently handled through an event system instead of through a mix of events and overridden methods. For example, BoardCanvas registers a PaintListener that draws the checkerboard; whereas, BoardPanel (see Listing 1) must override the paint() method. Changing the size of the board is done in the same way as you see in the code, with a selection event listener.
In SWT, widgets are not explicitly added to Composites. They are created with a parent and automatically added to it on creation. For platforms that support it, the parent of a widget can be changed with setParent(). Perhaps the most noticeable difference between SWT and Swing is that SWT requires you to explicitly manage the event loop, as is done in the main() method (see Listing 2). An explicit event loop allows the native window system to perform optimizations that would be bypassed with a hidden loop. For example, when multiple region drawing events get queued, overlapping regions can be merged into a single region and one draw event. Swing's hidden loop constantly dequeues events, turning them into Swing events on a Swing queue, and doesn't allow the window system to merge events.
Consider the Trade-Offs
I've avoided discussing the SWT API in too much detail because my intent was to show that Swing isn't the only approach to implementing cross-platform GUIs in Java. If you choose to use SWT or some other GUI toolkit, it should be because your needs dictate it. Figure 2 shows the SWT version of the program example running on Linux with the GTK window toolkit. It looks and behaves just like any other GTK-based GUI. Some applications, such as the Eclipse IDE, require native look and feel for a wide variety of platforms and cannot be served by Swing. Performance can also be a requirement. The Swing version of the program example is a little sluggish in changing dimensions when compared to the SWT version.
The advantages of using SWT come at a price. You now have to manage allocated resources such as fonts and colors instead of relying on automatic garbage collection to free resources. Whatever your requirements may be, knowledge of the trade-offs can help you decide which Java GUI is right for your application.
About the Author
Daniel F. Savarese is an independent software developer and technology advisor. He has been the founder of ORO, Inc., a senior scientist at Caltech's Center for Advanced Computing Research, and vice president of software development at WebOS. Daniel is the original author of the Jakarta-ORO text processing packages and the NetComponents network protocol library. He is also a coauthor of How to Build a Beowulf and is working on several book projects.
|