The Java 2 user interface
Graphical and user interface capabilities have progressed in leaps and bounds since the early days of the Java language. The Java 2 platform contains a sophisticated cross-platform user interface architecture that consists of numerous high-level components, an advanced feature-rich device-independent graphics system, and a host of multimedia extensions. In this article, we'll explore this progression, examine the capabilities of the current version 1.3 in detail, and finish by looking to the future to see what release 1.4 will offer.
Prior to the release of the Java 2 platform, the Abstract Window Toolkit (AWT) was the extent of the Java platform's graphical capabilities. Various technologies, such as Swing, were introduced as optional extensions. With the Java 2 platform, most of these extensions have found their way into the core as part of the Java Foundation Classes (JFC). JFC refers to the entire set of graphical and user interface technologies included in the Java 2 platform, including AWT and Swing. In this article, we'll explore each of the major components of the JFC and then discuss some of the optional extensions.
The heart of the JFC: Swing
Swing, a GUI toolkit with a rich set of components, forms the heart of the JFC's user interface capabilities. It is both a replacement for the components the AWT provides and also a big step forward.
When integration was the priority
In the first releases of the JDK, integration with the native platform was considered a priority and so the AWT provided components that were implemented using the native components of each platform (in the Java programming vernacular, these are now known as heavyweight components). For example, on UNIX platforms the java.awt.Button class was implemented with a Motif PushButton widget.
The same Java application had a different appearance on each platform, but the intention was that the different implementations were functionally equivalent. Of course, this is where the problems start. For simple interfaces, the equivalence is true, but the model breaks down as complexity increases simply because the components are different, and they will always behave slightly differently in some situations no matter how many bugs are fixed and how many times parts of the AWT are rewritten.
The other problem that cropped up by placing a priority on integration was functionality. The AWT provided only a limited set of components because of the "lowest common denominator" approach -- a particular component or function can only be provided if it is available on every platform. A classic example is mouse buttons. Back in JDK 1.0.2, there was no way to distinguish between mouse button presses because the Macintosh had only one mouse button, and so every other platform had to behave as if it too supported only one mouse button.
As the language became more of a platform in its own right, the approach to GUIs moved toward identical appearance and behavior across all platforms. To achieve this goal, the native components have to be abandoned as much as possible. But, clearly, some native code is still required. You can't make a window appear on UNIX without X System Window calls being involved.
Enter Swing, which achieved this goal by making use of a subset of the AWT, including the basic drawing operations and the certain classes in the java.awt package: Container, Window, Panel, Dialog, and Frame.
Best of all possible approaches
Swing does not completely follow the "Java language as a platform" route. Instead, it combines the best of both approaches by offering a bridge back to the native platforms.
The mechanism for establishing this bridge is referred to as Pluggable Look-and-Feels (which is pretty close to the concept of themes, popular in the Linux community). Each Swing component has a model of its functionality and a separate appearance (the look-and-feel), which can be set in advance or changed on the fly.
Swing provides a Java look-and-feel (previously known as Metal), separate ones for the Windows and Motif platforms, and one for the Macintosh platform (as an extra option). The platform look-and-feels don't use the native components of the platform like the AWT does. Instead, they use lightweight components that are drawn to have the same appearance as the native components. This is good for functionality, but there are always some differences in look or behavior, so complex interfaces will never be identical to ones that use native components.
Furthermore, you can roll your own look-and-feel, which is a great ability to have when crafting one for highly specialized applications or when providing a corporate look-and-feel across a range of applications.
Platform-independent drag and drop
JDK 1.1 added a general mechanism, found in the java.awt.datatransfer package, that enabled the transferring of data between and within applications, as well as the ability to manipulate the system clipboard.
The java.awt.dnd package was introduced in the Java 2 version. This package builds on the data-transfer mechanism by providing drag-and-drop facilities that can operate in a platform-independent manner within a single Java application or between two Java applications. It can also behave in a platform-dependent manner in order to integrate with the drag-and-drop facilities of the native platform.
The Drag and Drop (DND) API is quite challenging to use because it operates at a high level of abstraction to support the different ways in which it can work and because it is designed to operate on arbitrary datatypes, as specified by the java.awt.datatransfer.Transferable interface. Let's take a look at an example.
Enabling the disabled: Accessibility
The JFC Accessibility API equips Java applications so they can be accessed by users of all abilities, including people with sight-, hearing-, or dexterity-related difficulties. These might include the inability to discern visible or auditory cues or to operate a pointing device.
Two of the most important features of accessibility support are screen readers and magnifiers. Screen readers allow users to interact with a GUI by creating an off-screen representation of the interface and passing this to a speech synthesizer or a Braille terminal. Screen magnifiers provide an enlarged window of the screen, typically from 2 to 16 times the normal size. They generally keep track of pointer movements and changes in input focus and adjust the enlarged view accordingly. In addition, techniques such as font smoothing may be used to create a clearer picture.
The Java Accessibility Bridge
Some host systems, such as Microsoft Windows, provide their own accessibility features. By default, Java applications do not fully support them. For example, with native applications the screen magnifier detects when the input focus is switched to a different user interface component, such as by using the Tab key, and it adjusts the portion of the screen that is being magnified to show the component that now has the input focus.
However, Swing applications use lightweight components, which are treated as images by the operating system, instead of discrete components. This means the screen magnifier cannot track changes in input focus in the same way as with native applications.
This is exactly the problem the Java Accessibility Bridge for Windows solves. It creates a map between events relating to lightweight components and native system events. By using the Bridge, Java applications that support the Accessibility API are then fully integrated with the Windows accessibility support.
From primitive to advanced: Java 2D
Before the Java 2 platform, graphical capabilities in the language were rather primitive, limited to solid lines of single-pixel thickness; a few geometric shapes such as ovals, arcs, and polygons; and basic image-drawing functionality. All that changed with the introduction of the Java 2D API, which contains a substantial feature set.
The core of this API is provided by the java.awt.Graphics2D class, which is a subclass of java.awt.Graphics. The remainder of the API is provided by other packages within the java.awt hierarchy, including java.awt.color, java.awt.font, and java.awt.geom.
The java.awt.Graphics2D class
This class is a subclass of java.awt.Graphics, the class that provided graphical capabilities prior to the Java 2 release. The reason for this arrangement: backwards compatibility. Components are still rendered by calling their paint() method, which takes a Graphics object.
In the current version of the language, though, the object is really a Graphics2D object. This means that a paint() method can either use the Graphics object as a Graphics object (using the old drawing methods) or cast it to a Graphics2D object. If it uses the second option, then any of the additional capabilities of the 2D API can be used.
The java.awt.geom package
The java.awt.geom package provides a number of classes relating to two-dimensional geometry, such as Arc2D, Line2D, Rectangle2D, Ellipse2D, and CubicCurve2D. Each of these is an abstract class, complete with two non-abstract inner classes called Double and Float (which are subclasses of the abstract outer class).
These classes allow the various geometric shapes to be constructed with coordinates of either double or float precision. For example, newEllipse2D.Float(x,y,w,h) will construct an ellipse bounded by a rectangle of width w and height h, at position (x,y), in which x, y, w, and h are all floating-point values.
Also in this package is the AffineTransform class, which forms a core element of the 2D API. An affine transformation is one in which parallel lines remain parallel after the transformation. Examples of this type of transformation include such actions as translation, rotation, scaling, shearing, or any combination of these. Each transformation can be represented by a 3x3 matrix that specifies the mapping between source and destination points for the transformation.
Instances of the AffineTransform class can be created directly from a matrix of floating-point values, although they are more usually created by specifying one or more translation, rotation, scaling, or shearing operations. Mostly double-precision values are used, and angles are measured in radians (not degrees as used by the Arc2D class).
Text rendering
The text capabilities of the Java 2D API are impressive. They include:
Anti-aliasing and hinting for improved output quality
The ability to use all the system-installed fonts
The ability to apply the same operations (rotation, scaling, painting, clipping, and so on) to text as to graphic objects
Support for adding embedded attributes to strings (such as font, size, weight, and even images)
Support for bi-directional text (to enable right-to-left character runs like you would encounter in Arabic and Hebrew)
Primary and secondary cursors that can navigate through text containing both right-to-left and left-to-right character runs
Advanced font-measurement capabilities, surpassing those of the old java.awt.FontMetrics class
Layout capabilities to word-wrap and justify multi-line text
Multimedia options: Java Media APIs
The Java Media APIs are a set of resources covering an extensive range of multimedia technologies. Some of them, such as the 2D and sound APIs, are part of the core J2SE platform; the rest are currently optional extensions, but some of them will no doubt find their way into the core in the future. The other APIs in this area are Java 3D, Advanced Imaging, Image I/O, the Java Media Framework (JMF), and Speech.
Java 3D
The Java 3D API provides a set of object-oriented interfaces that support a simple, high-level programming model, enabling developers to build, render, and control the behavior of 3D objects and visual environments.
The API includes a detailed specification document and implementation for packages javax.media.j3d and javax.vecmath.
Advanced Imaging
Operations covered by this specification enhance a user's ability to manipulate images. It includes such operations as contrast enhancement, cropping, scaling, geometric warping, and frequency domain processing.
This type of functionality is applicable to various fields, such as astronomy, medical imaging, scientific visualization, meteorology, and photography.
Image I/O
This API defines a pluggable framework for reading and writing images of various formats. This new API is being designed through the Java Community Process.
Java Media Framework (JMF)
The JMF is an API for incorporating audio, video, and other time-based media into Java applications and applets. This optional package extends the multimedia capabilities of the J2SE platform.
Speech
The Java Speech API allows developers to incorporate speech technology into user interfaces for Java applets and applications. The API specifies a cross-platform interface to support command-and-control recognizers, dictation systems, and speech synthesizers.
This blanket API is divided into several specifications:
Java Speech API Specification (JSAPI)
Java Speech API Programmer's Guide
Java Speech API Grammar Format Specification (JSGF)
Java Speech API Markup Language Specification (JSML)
There is no Sun reference implementation for this API, but there are numerous third-party implementations, including Speech for Java (available from IBM alphaWorks), which uses ViaVoice to support voice-command recognition, dictation, and text-to-speech synthesis.