After completing this chapter, you should able to write, run, and deploy SWT/JFace-based Java programs.

Preparation

Before you start programming with SWT/JFace, you have to download SWT/JFace packages and configure your Java IDEs.

Downloading and Installing SWT JFace

Both SWT and JFace are included in the Eclipse distributions. From Eclipse version 2.1, SWT binary and source code can be downloaded separately from the Eclipse distribution. However, there are no separate JFace distributions.

If you plan to use SWT only, all you need to do is download the latest SWT binary and source code. If JFace is required, you can do one of the following:

Retrieve the code for JFace from the CVS of the Eclipse project and build it yourself

Download the complete Eclipse SDK

The latter method is much easier than the former one. You will use the latter method here.

Download the latest release or stable build of Eclipse SDK from http://www.eclipse.org/downloads. There are different distributions for various platforms, and you need to choose the corresponding distribution file to the platform you are running.

Decompress the release file. On Windows, you can use WinZip or Windows' built-in unzip utility to unzip the file; on Linux/Unix, try to run unzip eclipse-SDK-3.0xxx.zip. A folder named eclipse will be created. The complete Eclipse SDK is contained in this folder.

Later in this book, this folder is referred to as $ECLIPSE_HOME. When you meet $ECLIPSE_HOME, always replace it with your actual installation folder.

Check your Java runtime environment (JRE) version. On the download page of the Eclipse SDK, the minimum JRE is specified. Check your current JRE version by typing the following command: java -version. If there is no JRE installed in your system or you are using an unsupported version of JRE, you must download and install the latest JRE.

Finally, test your installation by executing the file $ECLIPSE_HOME/eclipse[.exe]. On Windows, you can simply double-click the file. On Linux/Unix, type the file's complete file path to run it. You should see a flash window followed by the Eclipse IDE workbench.

Note

This book focuses on two major platforms: Windows and Linux. You can easily apply the knowledge to other platforms.

Configuring Your IDEs

SWT/JFace does not depend on the Eclipse workbench, so you do not have to use Eclipse as your Java IDE. Here, you learn how to configure your IDEs to develop SWT/JFace-based programs.

Configure Eclipse

To configure Eclipse, follow these steps:

Create a project if you do not have one yet. To create a project, open the Eclipse workbench and select File→New→Project from the menu. You can specify project settings in the new project wizard; be sure to create a Java Project.

Add SWT jars to your classpath. Right-click a Java Project, and select Properties. Select Java Build Path from the left panel of the Properties dialog. On the right panel, select the Libraries tab. Click Add External JARs to add SWT JAR files. To use SWT only, you need to add all the JAR files under the directory:

in which NATIVE_WINDOW_SYSTEM should be replaced by the name of the underlying native window system and x.x.x represents the version number.

For example, on Windows, there is only one JAR file, swt.jar, under the directory $ECLIPSE_HOME pluginsorg.eclipse.swt.win32_3.0.0wswin32. However, on Linux, there are three files (Eclipse SDK, stable build 3.0M6) under directory $ECLIPSE_HOME/ plugins/org.eclipse.swt.gtk_3.0.0/ws/gtk: swt.jar, swt-mozilla.jar, and swt-pi.jar. As mentioned in previous chapters, SWT provides different sets of widget classes for each platform — thus the file swt.jar in the Windows distribution is completely different from its counterpart in other distributions. You should not use swt.jar in the Windows distribution on Linux because it will not work at all.

Now you have a clear understanding of which JAR files should be included. Adding those JAR files to the project's classpath is very straightforward. Click the Add External JARs button, and select the target JAR file. Then press OK; the JAR file appears in the build path as shown in Figure 3-1. Alternatively, you can use the Add Variable option.

Figure 3-1

To have more user-friendly content assist, you could attach the source code for the JAR files you added. The source files are located at the following directory:

Let's call them "auxiliary JFace packages." You need to add them to your classpath also.

Click OK to save your classpath setting and close the Properties dialog.

In addition to Eclipse, you can develop SWT/JFace-based programs on other IDEs.

Configure JBuilder

Setting up the classpath in JBuilder is very similar to doing it in Eclipse:

Create a project if you do not have one yet. To create a project, open the JBuilder IDE (JBuilder version: Enterprise 10.0) and select File→New Project from the menu. You can specify project settings in the new project wizard.

Add SWT/JFace JAR files to the classpath of the project. The JAR files required are given in the last section. Right-click the project, and select Properties from the menu. On the tree in the left panel, select Paths. Select the Required Libraries tab at the bottom of the Paths panel. Click the Add button and a dialog pops up. Click New to create a new library set. In the new library wizard, specify the name for the library, such as SWT-JFace, and then click Add to add each of the JAR files required. Click OK to add the newly created library to the project, as shown in Figure 3-2.

Figure 3-2

Click OK in the Properties dialog to save your classpath setting and close the Properties dialog.

Your First SWT Program

You have already set up your IDEs, and now you can develop your first SWT program.

Coding Your First SWT Program Hello World

The following code is probably the simplest SWT program. When it is executed, a window with the title "Hello, world!" pops up, as shown in Figure 3-3.

At the beginning of the main method, a Display object and a Shell object are created. The Display object is responsible for managing the connection between SWT and the underlying native window system. One of its primary functions is to implement the SWT event loop in terms of the platform event model. For almost all the SWT applications, only a single Display instance is required. The Shell object represents the window shown in Figure 3-3. The Shell object is linked to the Display object in the constructor. Once this linkage exists, you can get the Display from the Shell anytime with the getDisplay() method.

After the shell is created, set the window title by calling its setText method. Then open the shell by calling the open method, and a window appears immediately when this line is executed. Finally, set up an event loop to listen and react to events. When the user closes the window, the shell is disposed of and the event loop is broken. The program exits right after the disposal of the Display object.

If you do not have any experience with native UI programming, you may be confused about the event loop. It simply reads and dispatches events. Details on the SWT event handling mechanism are covered thoroughly in Chapter 4.

Running Your First SWT Program

As you saw in previous chapters, SWT employs JNI mechanisms to communicate with the underlying native window systems. Before you run your SWT programs, make sure your JRE can find those native libraries that SWT depends on. Otherwise, you may encounter the following exception:

java.lang.UnsatisfiedLinkError: no swt-win32-3024 in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1403)
at java.lang.Runtime.loadLibrary0(Runtime.java:788)
at java.lang.System.loadLibrary(System.java:832)
at org.eclipse.swt.internal.Library.loadLibrary(Library.java:100)
at org.eclipse.swt.internal.win32.OS.(OS.java:46)
at org.eclipse.swt.widgets.Display.internal_new_GC(Display.java:1411)
at org.eclipse.swt.graphics.Device.init(Device.java:541)
at org.eclipse.swt.widgets.Display.init(Display.java:1436)
at org.eclipse.swt.graphics.Device.(Device.java:96)
at org.eclipse.swt.widgets.Display.(Display.java:306)
at org.eclipse.swt.widgets.Display.(Display.java:302)
at com.asprise.swt.example.ch03.HelloWorld.main(HelloWorld.java:21)
Exception in thread "main"

where NATIVE_WINDOW_SYSTEM, OPERATING_SYSTEM, and ARCHITECTURE represent the name of the underlying native window system, the name of the underlying operating system, and the name of the hardware architecture, respectively.

The native library directory for Windows (Windows on x86) is:

$ECLIPSE_HOMEpluginsorg.eclipse.swt.win32_x.x.xoswin32x86

and its Linux counterpart (Linux on x86) is:

$ECLIPSE_HOME/plugins/org.eclipse.swt.gtk_x.x.x/os/linux/x86

You need to add the following virtual machine (VM) argument when you run SWT/JFace-based programs:

-Djava.library.path=$SWT_NATIVE_LIBRARY_PATH

If you need to run SWT programs from the Eclipse workbench, you can add the argument in the Run dialog, as shown in Figure 3-4.

Figure 3-4

You can configure other IDEs in the same way.

There are many other ways to add the SWT native library path to your Java library path. The most convenient approach is probably adding the SWT native library path to your platform-specific variables.

On Windows: Adding the SWT native library path to the PATH variable. Right-click the My Computer icon and select Properties from the menu, and the System Properties dialog appears. Select the Advanced tab and click the Environment Variables button to append the SWT native library path to the PATH variable.

On Linux: Adding the SWT native library path to the $LD_LIBRARY_PATH variable. Execute the following commands:

[Bash Shell] > export LD_LIBRARY_PATH=YOUR_SWT_NATIVE_LIB_PATH

[C Shell] > setenv LD_LIBRARY_PATH YOUR_SWT_NATIVE_LIB_PATH

You can append these commands to the startup files of the corresponding shells to set the variable automatically on each subsequent login. If you take this approach, you do not have to specify the SWT native library path whenever you run an SWT/JFace-based application.

Creating a Bigger Application Temperature Converter

The Hello World program does nothing but print the window title. Let's create some practical application with SWT. Here, you are going to create a temperature converter that can convert temperature readings in Fahrenheit into their Celsius equivalents and vice versa. The GUI of this application is shown in Figure 3-5. When a user types a temperature reading in the Fahrenheit text field, its equivalent Celsius value will be displayed in the Celsius text field. The same mechanism applies to Celsius-to-Fahrenheit conversion.

SWT classes such as Button and Label share the same names with their AWT counterparts. One of the common mistakes is using AWT components in SWT programs. So make sure you import widgets from SWT/JFace packages instead of AWT packages.

For this application, you put all the GUI construction code in the constructor:

At the beginning of the constructor, you set the title of the shell and its layout. A layout defines a positioning algorithm applying to the children of a composite whenever it's resized. Here, you set a RowLayout instance as the shell's layout. The RowLayout class is a layout placing all the child widgets either in horizontal rows or vertical columns with the composite. Chapter 6 is dedicated to SWT layouts.

After the layout of the shell has been set, you can add all the widgets that you need. To do that, you simply put the shell as the first argument in constructors of those widgets. The style of a widget can usually be specified in the second argument. A label is added to the shell to display status information.

To enable the application and react to the user's input, you need to use event listeners to listen to interested events and react accordingly. In this application, you need to listen to text modification events generated from both text fields. A ModifyListener is created and registered to both text fields to listen to modification events. When the user modifies the content of any of the text fields, the function modifyText in the listener will be called with a ModifyEvent object. Then the function makes a call to the custom function valueChanged.

The valueChanged method is quite easy to understand. It first detects which text field is the event source. If the event source is the Fahrenheit text field, it tries to perform Fahrenheit-to-Celsius conversion and the calculated value will be put into the Celsius text field; otherwise, it performs Celsius-to-Fahrenheit conversion and puts the calculated value into the Fahrenheit text field.

When a Text's setText is called programmatically, the Text generates a ModifyEvent. The current focus control check at the beginning of the valueChanged method helps to prevent the event handling deadlock.

The first thing you may notice is that the TemperatureConverterJFace class is inherited from the org.eclipse.jface.window.ApplicationWindow class. An ApplicationWindow instance is a high-level "main window," which has built-in support for an optional menu bar, an optional toolbar, and an optional status line. It also wraps the event loop inside itself. In the constructor of the TemperatureConverterJFace class, a null parent is passed to the super class's constructor, indicating that this window is a top-level window. The addStatusLines method adds a status line to the window for the purpose of displaying messages.

In order to add temperature conversion widgets to the window, you need to override the createContents method:

The preceding GUI-building code is very similar to that used in the SWT version of the temperature converter. The method createContents(Composite parent) will be called after all other widgets (optional menus, toolbars, status line, and so on) have been created and before the window is opened. The parent argument passed is the shell instance representing the window. The expected return type for this method is Control. If you need to add multiple widgets, you should create a top-level composite containing all the widgets and return the composite, as shown in the preceding code.

The event listener registration procedure is the same as that using SWT. There are some minor changes in the valueChanged method:

The setStatus method in ApplicationWindow is used to set the message to be displayed on the status line. In the SWT version, you create a Label object and use its setText method; here, the ApplicationWindow manages this for you.

The GUI of this JFace implementation (as shown in Figure 3-6) is more appealing than that of the SWT implementation, especially the status line part.

Figure 3-6

Besides the status line, ApplicationWindow can help you to simplify other common tasks such as menu creation and toolbar creation, which is covered in later chapters.

SWT JFace Software Deployment with Java Web Start

You have completed your SWT/JFace applications; now it's time for you to deploy those applications to the end users. Here, you learn how to use Java Web Start to deploy your applications to multiple platforms.

Introduction to Java Web Start

The Java Web Start technology provides a robust and flexible deployment solution for Java applications. With Java Web Start, you can deploy your applications through the Web easily. When a user clicks a link to a special Java Network Launch Protocol (JNLP) file, this brings up the Java Web Start software, which then automatically detects the current running environment and downloads, caches, and runs the given Java application.

To download Java Web Start software and to find more details on the topic, please visit Sun's Java Web Start home page at http://java.sun.com/products/javawebstart.

*.jar, *.dll, and *.os represent all the JAR files, DLL files, and OS files, respectively, under the specified directory.

Note that in the preceding table, not all the auxiliary JFace packages are included. Some of the auxiliary packages are not required by this simple application; you can omit them to reduce the total size of the deployment files. If you are not sure whether an auxiliary package is required or not, you should include it to avoid possible ClassNotFound exceptions.

Packaging and Signing Files

According to the Java Web Start Specification, applications with unsigned JAR files are restricted to run in a secure sandbox, which prevents them from calling native libraries. Because the temperature converter application depends on the SWT native libraries, you have to sign all the files to remove this restriction.

The Java Web Start Specification requires that all applications be delivered as a set of JAR files, so you have to package non-JAR files into a set of JAR files. Because the Java libraries of SWT/JFace are already in the JAR format, there are only two kinds of files you need to pack up into JAR files:

Your application code (Java classes, property files, and resource files): Most IDEs export these into JAR files or you can use the jar command. For the temperature converter application, you need to pack the class file into a JAR file (tc.jar):

jar cf tc.jar CLASS_OUTPUT_DIRECTORY

Native libraries: Similarly, you can put all the required native libraries into one or more JARs:

You need to download and unzip both Windows and Linux releases of Eclipse SDK regardless of the type of operating system you're running. In the preceding commands, $ECLIPSE_WIN32_HOME and $ECLIPSE_LINUX_HOME represent the home directories of the Eclipse SDK Windows release and the Linux release, respectively.

Now all the files to be deployed are packed, as shown in the following table.

Now, you can digitally sign the JAR files. Signing files lets people know that you are the genuine distributor of the files. You need a public key, a private key, and a certificate to sign files. If you do not have them yet, you can use the following command to create a dummy set of public key, private key, and certificate using Sun's keytool:

The preceding command creates a public key, a private key, and a self-signed certificate in the file dummy.keystore. However, I recommend that you obtain a certificate from a certificate authority and that you use it in production.

Let's write a JNLP script that will be used to inform the Java Web Start software on the client machines about the temperature converter application. Such details such as the title and vendor of the application, required resources, and main class are included in the JNLP script as follows:

The top-level element in a JNLP file is . In the preceding code, specify the following attributes:

spec: The JNLP specification version

codebase: The base for all relative URLs specified in the href attribute

href: The URL pointing to the JNLP file itself

The information element is used to provide information about the application, such as its title, description, and icon.

Next, request the Java Web Start software to grant the application all the permissions:

Then, tell the Java Web Start software which files are needed to run the application:

The first resources element, which has no attributes specified, specifies all the shared code across all kinds of platforms. The second resources element specifies extra files required on the Windows platform. Similarly, the last resources element indicates extra files required on the Linux platform. The Java Web Start software uses this information to determine the file set to be downloaded.

Finally, you need to tell the Java Web Start software your main class to start the application:

Now, you are ready to upload all the files to your Web server.

Uploading and Running

First, you need to configure your Web server to recognize JNLP files by adding the following MIME type to the Web server's configuration files:

application/x-java-jnlp-file JNLP

You can let the user point directly to the absolute path of the JNLP file or you can use a launch HTML file. The latter is more user-friendly. You can create a launch page that's as simple as the following:

Click <a href="tc.jnlp">here</a> to launch Temperature Converter.

Save this HTML file as index.html and put it with the JNLP file tc.jnlp under the directory javaui/tc. Upload the whole javaui directory to your Web server.

Now you can visit the launch page at www.asprise.com/javaui/tc/index.html. Click the link to launch the JNLP file. The Java Web Start software downloads and parses the JNLP file for information and resources about the application. After all the information is obtained, it starts to download required files, as shown in Figure 3-7.

Figure 3-7

After all the required resources are downloaded, the Java Web Start software tries to start the application. First a warning message complaining that the certificate cannot be authenticated (because you used a dummy certificate) appears, as shown in Figure 3-8. Click Start to start the application.

Summary

This chapter helped you to jump start programming with SWT/JFace. First, you need to download and install the SWT/JFace library. After obtaining the library, you need to configure your favorite Java IDE (Eclipse, JBuilder, and so on) to add SWT/JFace library jars into Java path. Then you can start coding your SWT/JFace-based programs. Creating SWT-based programs is very straightforward; you can use a Display object to open a window (represented by the Shell class). Alternatively, you can develop JFacebased programs. Because JFace handles many common UI tasks, the code length is likely to be reduced. After you write and test your programs, you are ready to deploy them. The Java Web Start technology is becoming more and more popular. The last part of this chapter guides you to deploy your programs to multiple platforms using Java Web Start.

An event loop always exists in an SWT program. The next chapter demystifies the event loop and explains SWT event handling mechanisms.