dcsimg

Is Swing Being Eclipsed?

In a little more than a year, the Eclipse project initiated by IBM has become one of the most dynamic and widely-supported open source efforts of any kind, especially within the Java community.

In a little more than a year, the Eclipse project initiated by IBM has become one of the most dynamic and widely-supported open source efforts of any kind, especially within the Java community.

Eclipse, an integrated development environment (IDE) and application framework written entirely in Java, is a programming language-independent and tool-agnostic platform designed from the ground up to be extended by plug-in tools. In fact, the only core components of the software do nothing more than boot the application and load plug-ins — everything else is a plug-in. The Eclipse platform is available on the Web at http://www.eclipse.org, a site published and maintained by the Eclipse Consortium group, which includes Red Hat, SuSE, and QNX among its members.

An article in the April 2003 issue of Linux Magazine (available online at http://www.linux-mag.com/2003-04/eclipse_01.html) described Eclipse’s use as a “world-class Java IDE,” showing how it supports a robust selection of features, including refactoring, code completion, intelligent templates, CVS, and tools such as Ant, JUnit, and make. Indeed, because it’s getting so much attention as an IDE, Java programmers who are happy with their own development tools may be paying little attention to Eclipse, thinking that’s all it is.

But that’s a shame, because Eclipse has valuable features for Java programmers: Eclipse has its own application framework and offers the Standard Widget Toolkit (SWT), a set of graphical user interface packages that easily rivals Swing, the Abstract Windowing Toolkit (AWT), and other libraries.

Jolting Java

Because Eclipse is 100% Java, you might naturally expect Eclipse to share some of the faults of other IDEs written with the language, such as sluggish performance and user interface quirks that differ from OS-specific software. (The original circa-1996 Java WorkShop from Sun was the Edsel of IDEs, performing at speeds that are charitably described as glacial.) But Eclipse dispels these negative preconceptions quickly. The program’s IDE looks and performs like native applications. All of the interface components function as if they were written with C, C++, or some other language that calls OS-specific APIs. Nothing about the program suggests that it’s written in Java.

Eclipse’s pleasant performance comes from the interface components, layout objects, and event-handling techniques of SWT, a toolkit that takes a radically different approach than Sun’s windowing packages.

SWT was designed to offer the same user interface components as native programs, but with an API that’s independent of any particular platform. SWT’s “hybrid” approach uses techniques that are radical for a Java class library: SWT is tightly integrated with native graphical user interface libraries and it’s a requirement to explicitly dispose of SWT objects after use.

Although SWT components offer the same API on different platforms in the manner of Swing, they are implemented on each platform with native components when native components are available and emulated otherwise. For instance, a tree component (SWT calls its components widgets) is emulated on Motif and implemented on Windows and Mac OS with native components found in the interface libraries of the latter two platforms.

Components make use of native libraries as much as possible. For example, a call to set or get the label on a button results in a direct call to the native component. Little information is stored in the SWT component. Interestingly, the integration is so tight that a change to a component’s look and feel is immediately reflected in the SWT user interface.

Internally, the SWT class library mimics the implementation of native windowing components, using the same method calls that would be used to work directly with a platform’s user interface libraries. Programmers with experience developing graphical user interfaces on a particular operating system can look at the SWT source and recognize the calls executed in response to an event.

Externally, even though SWT implementations are different on Linux and Windows and MacOS, they have the same public API. The end result is so seamless that IBM makes the following claim on its Web site: “An important side benefit of using SWT is that once you’ve developed a user interface on Linux, it is also a first class interface when applied to Windows. The reverse is also true.”

The most radical departure in SWT is in memory management, a subject that many Java programmers happily delegate to the automatic garbage collector. To use SWT, you must follow a few, hard-and-fast rules:

1. Always dispose of the components and graphics contexts that you create.

2. Never dispose of components and contexts you did not create.

3. Dispose of a parent to automatically dispose all of its children.

Listing One contains SalutonMondo, a Java application that uses SWT for its graphical user interface. The program creates and displays a frame with a label and a graphical button.




Listing One: The SalutonMondo application

package com.prefect.swt;

import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.RowLayout;

public class SalutonMondo {

public static void main(String[] arguments) {
Display display = new Display();
Shell shell = new Shell(display);
RowLayout layout = new RowLayout();
layout.justify = true;
shell.setSize(225, 125);
shell.setLayout(layout);
shell.setText(“Saluton, mondo!”);
Label label = new Label(shell, SWT.CENTER);
label.setText(“Saluton, mondo!”);
label.setLayoutData(new RowData(50, 100));
Button button = new Button(shell, SWT.CENTER);
Image owl = new Image(shell.getDisplay(),
“/java/swt/owl.gif”);
button.setImage(owl);
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent evt) {
shell.close();
shell.dispose();
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep ();
}
display.dispose();
owl.dispose();
}
}

Under the Hood

Before looking at the application, it’s worth noting that SWT uses different idioms than Swing to describe many of its core features — for example, components are called widgets or controls, frames and windows are called shells, and containers are called composites.

In spite of the differences in terminology, the basic process of developing and using an SWT user interface is familiar enough to be picked up in minutes by a Swing programmer.

The SalutonMondo application makes use of the base org.eclipse.swt package and three subpackages: org.eclipse.org.swt.graphics for the button graphic; org.eclipse.swt.layout for a layout manager; and org.eclipse.swt.widgets for interface components.

An SWT project begins by creating a Display object that brokers communication between the user interface and the native components that implement it. It takes no arguments.


Display display = new Display();

The Display object is used to create a Shell, which represents a top-level window (if it is the child of a Display object) or a secondary window such as a dialog box (if it is the child of another window).

Unlike Swing components, an SWT component must be assigned a parent at the time it’s created:


final Shell shell = new Shell(display);
shell.setSize(225, 125);
shell.setText(“Saluton, mondo!”);

An SWT application is a hierarchy of objects that’s topped by a Shell that represents the application’s main window. Containers for other components are descendants of the Composite class — a list that’s worth scanning to see what’s available: Canvas, CCombo, Combo, CoolBar, CTabFolder, DrillDownComposite, Group, OleClientSite, OleFrame, PageBook, ProgressIndicator, ProgressMonitorPart, SashForm, ScrolledComposite, TabFolder, Table, TableTree, ToolBar, Tree, and ViewForm.

The other components descend from a Control superclass: Button, Label, ProgressBar, Sash, Scale, Scrollable, and Slider.

When a component such as the Shell is created, the native implementation of that component is also created. This is the reason that a parent must be specified in the component’s constructor: most native user interface libraries require a parent as well.

SWT uses Layout objects to determine the arrangement of components within a Composite container:


RowLayout layout = new RowLayout();
layout.justify = true;
shell.setLayout(layout);

There are four standard layout classes: RowLayout for a simple words-on-a-page style arrangement of components; FillLayout for equal-sized components that occupy a single column or row; GridLayout for a rectangular grid of component cells; and FormLayout for more precise placement of components. To fine-tune some of the layouts, an xData class can be used to specify alignment of a specific child component when it is created:


Label label = new Label(shell, SWT.CENTER);
label.setText(“Saluton, mondo!”);
label.setLayoutData(new RowData(50, 100));

Each SWT component has an integer argument that specifies one or more styles that affect its presentation. These styles are class constants of the SWT class and are combined with a bitwise OR operator.

Event-handling in the SWT is highly similar to Swing: a Listener class is added to a component by calling an add…Listener method with one argument, the class that implements the corresponding Listener interface. Adapter classes are available that contain empty methods implementing the interface, making it easy to override only the methods needed.

The following statements add a SelectionListener to a button. This listener calls the widgetSelected() method when the button is clicked:


button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent evt) {
shell.close();
shell.dispose();
}
});

The thread that creates the Display object monitors and dispatches all events that occur as a user manipulates a component. For this reason, event-handling methods can use components in a threadsafe manner automatically. Any operation that takes considerable time in response to an event should be given its own thread — otherwise, some SWT events may be missed.

Listeners — including HyperlinkListener, MouseListener, and FocusListener, among many others — provide mechanisms for monitoring user interactions.

After a shell and all of its child components have been created, some boilerplate code can be used to display it and hang around until the shell has been closed by the user:


shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep ();
}

These low-level windowing techniques are enhanced in Eclipse with JFace, a high-level user interface toolkit that’s implemented using SWT, and plugin.xml, an XML dialect that enables the content of menus and toolbars to be specified without any Java code.

JFace serves as a bridge to complex SWT components, making it considerably easier to work with list, tree, table, and text components. A JFace object called a viewer is provided with the information needed to set up the component. If a component is being used to represent complex data, the viewer can automatically convert it from the form used by an SWT component to the form that you require.

The Eclipse Web site includes a considerable amount of documentation, though there isn’t much for someone who is just getting started. The software includes an org.eclipse .swt.examples package with several good, well-documented example applications such as a file viewer, text editor, address book, and drag-and-drop demonstration.

The performance of the Standard Widget Toolkit on Eclipse and other software make it a tempting choice for graphical Java applications.

Caveat Emptor

The SWT toolkit has a few drawbacks. It doesn’t have as wide a variety of components or functionality as Swing, and it introduces some unfamiliar, new hassles, such as the difference in implementation on each particular platform and the need to collect your own garbage.

But as Eclipse gains more momentum, it’s a safe bet that the SWT and JFace will continue to be enhanced because the platform and all Eclipse plug-ins are built with them.

SWT makes possible some interesting possibilities on Linux. Thinking back to last month’s Java Matters column on alternative Java development tools, one project springs to mind immediately: a Java application that uses SWT and is compiled with the GNU Compiler for Java (GCJ), producing native code with a speedy and familiar graphical user interface.

The next edition of Java Matters will cover another exciting new development, the Java Server Pages Standard Tag Library (JSTL), a group of tags that comprise the core functionality of a Java Server Pages Web application.



Rogers Cadenhead is a Web application developer and the coauthor of Teach Yourself Java 2 in 21 Days, Third Edition from Sams Publishing. To contact Cadenhead, visit his weblog at http://www.cadenhead.org/workbench.

Comments are closed.