The foundation class sets in the Java world have evolved rapidly in the past year. JavaSoft's Java Foundation Classes (JFC), succeeding the JDK's Abstract Windowing Toolkit (AWT) and Netscape's Internet Foundation Classes (IFC), has taken on the mission to continue battling Microsoft's Application Foundation Classes (AFC). JFC is released as a separate collection of packages designed to work smoothly with JDK 1.1; these packages will be making their way into the core of Java as integral part of JDK 1.2. AFC, taking great pains to be backward-compatible with JDK 1.0, can work impressively with JDK 1.1; and its design and implementation technically doesn't prevent it from being upward-compatible with future JDK releases. We consider both AFC and JFC to be very promising. They are both here to stay.
Many developers are wrestling with the question of which technology to use in their application development. It seems JFC and AFC have divided the world of Java graphical user interfaces (GUIs) into two camps. Putting aside the political issues, marketing hype, and personal religions, this article offers a comprehensive examination and comparison of JFC and AFC and provides some insight designed to help you choose the GUI toolkit that's best for you.
The basics: AFC and JFC components
JFC consists of five components:
- Swing (the Java GUI toolset)
- The Java 2D API
- The accessibility API
- A drag-and-drop framework
AFC is Microsoft's alternative to JFC Swing. Its core packages include:
- UI, an equivalent of JFC Swing and AWT
- FX, a package that provides improved support on graphics, font and color and some supporting utility classes
Note that drag and drop is not inherent to AFC, but an AFC application can have drag-and-drop capability if the Microsoft Java software development kit (SDK) is being used.
In this article we focus mainly on the comparison between JFC Swing and AFC, although we also will discuss in brief the 2D framework, accessibility, and drag-and-drop features. For convenience, however, in the following text we simply use "JFC" to refer to any subset of JFC.
Design philosophy and general architecture
Both JFC and AFC strive to provide a better GUI framework than the original AWT in JDK. Goals include better performance and a more consistent look and feel across platforms with different Java implementations. Both JFC and AFC have made available a comprehensive set of GUI components sufficient for development of most Java-based GUI applications. JFC and AFC share some similar goals:
- Lightweight or "peerless" (GUI components that do not have native opaque windows associated with them)
- High performance
- Consistent look and feel across platforms
- Richer set of GUI components with advanced features
- Pure Java implementation (no native libraries are involved)
Despite these similar goals, AFC and JFC have been designed and implemented with distinctively different architectures:
- JFC is based on the JDK 1.1 Lightweight UI Framework, which allows creation of peerless components that fit seamlessly into existing AWT models. JFC components are derived from the AWT
Componentclass. AFC, in contrast, is based on its own lightweight framework -- it has its own class hierarchy that is parallel to JDK AWT's hierarchy. AFC components are not derived from AWT classes.
- JFC uses strictly the JDK 1.1 delegation event model. AFC supports both JDK 1.0 and 1.1 event models at the API level, but its core implementation of event propagation is completely 1.0-based. We will explain this in more detail in a later section.
- JFC supports the Model-View-Controller (MVC) architecture and pluggable look and feel. AFC enforces a single Windows look and feel across platforms.
The differences between the AFC and JFC architectures are no surprise. After all, AFC is intended as a replacement of the AWT, though it can accommodate AWT components through special facilities. JFC is an extension of AWT. It follows the AWT architecture, but adds to it the power of MVC and integrates with it the beauty of pluggable look and feel.
JFC Swing and AFC have different policies on supporting and implementing JDK 1.0 and 1.1 event models. As a result, the performance of these two systems differs considerably.
JFC Swing uses the JDK 1.1 delegation event model exclusively, partially because some of the JFC components use this event model inside their internal implementation. Typically, the look-and-feel implementation class of a JFC component needs to receive events for rendering the component's view correctly to exhibit certain behavior. The class usually registers its related code or even itself as the listener to its corresponding component. That is, communication between the JFC component classes and their corresponding look-and-feel implementation is usually reliant on the delegation event model for event passing. For example, a JFC tree look-and-feel implementation class adds itself as a mouse event listener to the
JTree component in order to receive mouse events. Due to the "all or nothing" event processing policy in JDK 1.1 (which determines the event model type of a component and processes all events on that particular component using exclusively the determined model), it is not safe to assume a JFC component can receive and/or propagate 1.0 type of event. To make it clearer, though JFC is extended from JDK 1.1 AWT, which is backward-compatible with the 1.0 event model, the JFC components do not inherit that backward compatibility.
The AFC event model, on the other hand, is a hybrid of both JDK 1.0 and 1.1 models. It provides 1.1 API support on top of a 1.0-model base implementation. Different from the "all or nothing" approach in JDK, AFC propagates all 1.1 events to its containment class in the hierarchy, as if those are 1.0 events.
Developers should be aware that even though AFC provides 1.1 event model API, it does not provide the benefit of the JDK 1.1 event model, which is supposed to eliminate duplicated and unwanted event propagation. Within AFC, we find that a 1.1 event listener registered with a container can possibly be triggered by a 1.0 event originated from a component inside the container. Thus, the application's performance is not only unable to improve, but also likely to become worse if an application mixes both 1.0 and 1.1 event models. In our opinion, the AFC event model has a serious performance hole and doesn't scale up in large applications.
Using exclusively the JDK 1.1 event model, JFC applications can achieve better performance with reduced event traffic. The trade-off with the JFC's approach of supporting only the 1.1 event model, however, is that the event-handling mechanism of all 1.0-compatible applications will need to be modified to upgrade to JFC. On the other hand, AFC provides an easier path for migration of applications using the old 1.0 event model.
A simple application with a button in a
On the right hand side, we illustrate the difference between the AFC and JFC event models. When the button in this application is pressed, AFC applications will make four event related calls, while JFC applications will make only one.
We assume an
Extensibility and flexibility
During GUI application development, developers are constantly confronted with two issues:
- The mechanism of associating GUI front-end prototype with back-end application logic and data
- The ways of putting existing and derived GUI components together to compose a powerful and impressive user interface
A common development practice that addresses the above two issues is to extend an existing GUI framework to incorporate application logic and then use the extended components as flexible building blocks to build applications. As a result, the extensibility and flexibility of both JFC and AFC is of concern to many developers.
Basically, sub-classing from AFC components or implementing AFC UI interfaces is the only way to extend AFC components. This approach is straightforward. With a lot of important methods opened and implemented in the top-level class of
UIComponent, developers should find it easy to derive customized components from
UIComponent or its subclasses that work smoothly with the AFC system.
There are three major ways to extend the JFC system:
First, if a unique look and feel is desirable, you may choose to either implement the JFC look-and-feel UI framework directly or extend one of the existing look-and-feel implementations.
Second, the data structures being used by the JFC components are highly extensible. Each JFC component points to a data-model interface and makes use of a default implementation of that particular interface. Developers can use the default data-model implementation in many cases, but can also extend the default implementation or even provide their own implementation to replace the default version.
- Third, if a desired component is completely unavailable in JFC and neither of the first two methods helps in any way (i.e., it is impossible to derive such a component through subclassing of existing JFC GUI components) one can work directly on the AWT Lightweight UI framework to create a lightweight component based on the AWT top-level
Componentclass or the JFC Swing top-level
JComponentclass. After all, the JFC MVC architecture, by detaching the GUI front-end of a component from the application-specific back-end data structure, has greatly reduced the need to derive customized GUI components for application development. In AFC-based or AWT-based application programming, however, the need to derive customized GUI components to incorporate application logic is frequent.
In terms of flexibility, JFC is well known for allowing programmers to fine-tune and switch the data structure of GUI components during development and letting users switch the look and feel in runtime. Considering the absence of MVC and pluggable look and feel in AFC, however, we think it's more appropriate to focus our discussion of this issue on other areas that both toolkits share. One such area is the flexibility of gluing together components to create customized user interfaces. In AFC it's generally possible to add virtually any component as a "child" to any other component. For example, while a simple component like a button or label could be added as a child node to a tree, it's also possible to add a tree as a child component to a button or label. As another example, composite components like list, ComboBox, or even table also could be added as nodes to a tree. The ways of composing components are not strictly defined but left wide open, regardless of whether the composition makes sense. On the other hand, despite the fact that each JFC component is a subclass of AWT
Container and therefore can be added programmatically to any other arbitrary JFC component, the process of adding a composite component as a child to a simple component usually yields unexpected results. There are two reasons for this:
First, a JFC component always reroutes its repaint request to its look-and-feel implementation class, which makes some assumptions about the contents of the component and renders those contents according to those assumptions.
- Second, some composite JFC components like
JTabledo not contain sub-components directly, but instead use special facilities called Renderer/Editor for data presentation. For example, if you add a
JButton's look-and-feel implementation assumes
JButton's contents to be text and/or images and will not render the tree for display. For another example, if you add a button as a node to a tree, the button's "look" is preserved but the "feel" -- say, the push-down/pop-up behavior that occurs when the button is clicked -- is lost.
We will not go into detail on the concepts of Renderer and Editor in this article. We will, however, note the difficulty of visualizing a collection of complicated, high-variety data items while using JFC composite components with the Renderer/Editor mechanism. AFC's approach is simpler, more explicit, and more flexible.
Integration with AWT
AFC UI components are not compatible with AWT because they are not derived from the AWT hierarchy. An AFC component cannot be added to an AWT container. (For example, a
UIButton can't fit in an AWT
Panel.) AFC does, however, provide facilities to allow integration of the two systems. AFC UI components, wrapped by their corresponding AWT adapters, could be easily added to any AWT container. For example, a
UIButton, wrapped by its AWT adapter
AwtUIButton, could be added to an AWT
Panel. AWT components, on the other hand, can also be hosted by an AFC container class
UIAwtHost to function properly in an AFC application.
JFC Swing components, derived from AWT
Component, are a natural extension of AWT and can be used together with any AWT native or lightweight components in the same container. Notice, however, that since it is based on the AWT Lightweight UI framework, the SwingSet also inherits one caveat from this framework -- the heavyweight sibling will always be "on top" if overlapping with a Swing component, regardless of the desirable painting order. But this is not a problem of the design and implementation of JFC itself. Those who are interested in this issue should refer to the JDK 1.1 AWT documentation for more detail.
While JFC Swing components are fully JavaBeans-compliant, AFC UI components currently are not. AFC 1.1 does, however, provide a
SimpleBeanInfo implementation for its various AWT adapter classes. Notice that these adapters, using the AWT
Panel as their very root class, seem to be beans-compliant. The question: Can these AWT adapters truly be used as bean objects to give users access to all the properties of their wrapped AFC UI components?
By default, AFC does not provide a JAR file for its components. To test the JavaBeans compatibility of the aforementioned wrapper classes, we packed all the related AFC packages into a JDK 1.1-compatible JAR file and tried loading the file into the JavaSoft Beans Developer Kit (BDK) BeanBox. As a result, we encountered some exceptions originated from AFC components. We've also performed similar tests using Symantec's Visual Café with no better luck. At this point, we can only conclude the AFC release has not been made fully JavaBeans compliant.
Migration from existing AWT and IFC applications
From AWT to AFC
Migration from AWT to AFC is relatively straightforward because the AFC model is similar to AWT in spirit. A simple guideline for migration is to change AWT control and layout class names to UI<classname>, and graphics class names to Fx<classname>. For example,
BorderLayout in AWT should be replaced with
Graphics in AWT should be renamed
FxGraphics. Since the AFC API is generally similar to AWT's, it's likely that much of the AWT code will continue to compile and even function properly, though the AFC constructors of many AFC control components are different from AWT and have to be set up properly. Awt2afc, a tool bundled with Microsoft Java SDK 2.0, simplifies the code conversion process by inserting suggestions and comments into the original AWT source code. However, manual conversion is still required to make the actual source code modifications.
From AWT to JFC
JFC, being a superset of AWT, makes migration from AWT a simple process, provided your AWT applications use the JDK AWT 1.1 event model. By adding the prefix "J" to the control component class names, you can easily turn an AWT application into a JFC Swing application. The layout manager classes will continue to work with JFC classes also. Existing event-handling code written with the
EventListener model will require very little change, if any.
If, however, the application to be migrated originally was written with the JDK AWT 1.0 event model, you have to perform substantial surgery, cutting the event-processing code and moving it to separate event-listener implementations. The effort of separating the event-handling code from the UI code, while not trivial, is worthwhile, considering the benefits it brings to future maintenance and enhancement.
Beside the class name and event model, one of the most important changes that a developer should consider in a migration process is the use of the MVC architecture of JFC.
From IFC to JFC
Netscape's Internet Foundation Classes (IFC) are said to be the predecessor of JFC. However, pre-release versions of JFC continue to evolve and, as of JFC Swing version 0.7, we are hard-pressed to find any similarities to its claimed predecessor. Although some important IFC features and ideas may have been borrowed and embedded into various parts of the JFC systems, the IFC-to-JFC migrating effort could range from simple name conversions in source code to major restructuring of an entire application. JavaSoft and Netscape have both promised tools to help developers migrate their IFC applications, but up to this point we haven't found useful information regarding the availability and technical details of these tools. Having used both class libraries extensively, our experience shows that an effective mechanism on automating the IFC-to-JFC source code conversion is very difficult to implement. We believe that heavy manual modification or even complete rewrite of the IFC source code is inevitable.
Portability and browser support
Because both JFC and AFC are written in pure Java, theoretically they can run on any Java virtual machines (VMs) on any platform. In the following table, we list major VMs and browsers that support JFC and AFC.
|Virtual Machine||Version||JFC||AFC 1.0.2||AFC 1.1|
|1.1.x||Yes||No **||Yes *|
|Internet Explorer||3.0.x||Yes (with Activator early access)||Yes||No|
|Netscape||3.0.x||Yes (with future Activator release)||Yes||No|
|4.0.4 with JDK 1.1 patch||Yes||Yes||Yes *|
* Note: See the sidebar "How to run Microsoft AFC applications using Sun's JDK 1.1" for more information.
** Note: Theoretically, AFC 1.0.2 can work with JDK 1.1-compatible VMs with 1.0 backward compatibility. But AFC 1.0.2 documentation has no reference for JDK 1.1 VM support, and we find AFC 1.0.2 fails to work correctly with JDK 1.1.x.
The original AWT proves to be insufficient to achieve impressive visual effects. AFC has relied heavily on a package called "Fx," which provides extensive font and color support, better text rendering, and an enhanced drawing-primitives API. AFC components are thus able to offer advanced features like text rotation, texture background, and complicated shape rendering. JFC's 2D API, on the other hand, provides a more powerful, flexible, and complete framework that addresses issues of font support, color management, printing, imaging, text rendering, spatial transformation, and related features in a much larger and deeper scope. As a fully functional and general-purpose 2D graphics and imaging programming framework, JFC's 2D API delivers much more than the Microsoft Fx package. Also notice that the 2D API framework is only loosely coupled with Swing, the UI framework, in the sense that Swing does not depend directly on the 2D API but can be enhanced visually through the use of the API in the implementation of its look-and-feel modules. The initial release of Swing is based on the AWT graphics support, and the future release promises to take full advantage of Java 2D. The Microsoft Fx package, on the other hand, is a key element in AFC. Not only AFC components but also AFC application code in many cases have to use Fx classes and interfaces directly.
Drag and drop is not part of the AFC packages. Though we do observe drag-and-drop capability from one of the AFC sample programs distributed by Microsoft, by tracing the code we determined that the Microsoft drag-and-drop implementation is heavily bound to the Windows platform, with native code involved. JFC addresses the issue with much better, robust solutions. It not only provides a platform-independent, drag-and-drop facility for Java GUI clients but also allows integration with platform-dependent, drag-and-drop facilities by permitting Java clients to participate in drag-and-drop operations with native applications.
Both AFC and JFC Swing have integrated "accessibility" into their implementations, thus enabling the construction of assistive technologies that help people with disabilities interact and communicate with their GUI components.
Learning curve and ease of use
As we discussed above, while JFC is extended from the existing JDK 1.1 AWT class hierarchy with each of its components being a subclass of the AWT
Component class, the Microsoft AFC derives its own top-level class
UIComponent directly from
java.lang.Object and has a separate class hierarchy irrelevant to AWT. Interestingly, though, AFC is similar in overall design to AWT. It is based on an architecture that maintains many of the concepts used by AWT. Anyone familiar with the original AWT concepts will easily understand AFC and be able to apply AFC concepts quickly.
JFC, on the other hand, has more ambitious goals that yield a more sophisticated API framework. Encompassing the MVC architecture and pluggable look-and-feel capabilities, JFC has introduced a certain level of complexity in the following aspects:
- JFC presents a data-centric programming model, quite different from other GUI-oriented toolkits with which most developers are familiar.
- JFC has introduced many new concepts (such as UIManager, DirtyRegionManager, Renderer, Editor, Tree RowMapper, and TreePath), either unique to its own architecture or not commonly found in other frameworks, that developers need to learn and understand.
- Advanced components like Tree, Table, TextComponent, and some others, though powerful, are not simple to use. None of their implementations are mapped to one simple GUI component class. Instead, the correct functioning of these components requires a set of related objects working collaboratively. A typical example is the Tree, which has its own package containing interfaces of
TreeSelectionModel, and classes of
TreePath. Some of these classes and interfaces make uses of concepts whose meanings are inexplicit. It's likely that a thorough understanding of them could only be achieved through the study of a combination of instructive documentation and code examples with extensive experiments. Other components like Table and Text also have their own object frameworks wrapped in their own packages. The API of each of these components is, by itself, a tiny programming framework that a developer needs to follow and understand.
In brief, before being able to fully utilize the power of JFC, an application developer has to learn and understand, in addition to the original AWT, the following:
- JDK 1.1 AWT event delegation model
- Model-View-Controller (MVC) architecture
- Concepts of Renderer/Editor and the way they are being used in composite components such as Lists, ComboBox, and Tree
- Tiny API frameworks specific to each advanced component
Additionally, a developer who wants to create new components extending the existing JFC classes needs to know and understand:
- JDK 1.1 AWT Lightweight UI Framework
- JFC pluggable look-and-feel architecture
- Concepts of repaint batching system (through interfaces and classes of
RepaintManager, and so on)
- Some details about 2D graphics
To use AFC, an application developer first must understand the JDK AWT theory while a component writer needs to know about AFC's own lightweight framework as well as some 2D graphics. The AFC API is generally consistent with the AWT style, and may seem intuitive to those who are familiar with AWT.
AFC, an AWT replacement that is architecturally independent of and incompatible with AWT, provides a set of APIs very similar to AWT in style that an AWT programmer can learn and use quickly. JFC, an AWT extension logically derived from the AWT hierarchy, provides a complicated framework that requires a longer learning curve for an AWT programmer who wants to fully exploit its great power. In brief, we feel that AFC has made a developer's AWT programming skill highly reusable while JFC, though preserving the usefulness of the skill, has diminished that skill's significance to make the experience with AWT insufficient. This is the trade-off for adapting the MVC architecture: You obtain its various benefits, but at a cost.
Microsoft AFC is easy to learn and use. It would possibly require less effort to migrate a JDK 1.0-based GUI application to JDK 1.1 using AFC. But AFC employs an event model that is outdated and inefficient. Components written with AFC also may have problems with beans compliancy. Notice, too, that AFC is currently tightly bundled with Microsoft Internet Explorer and SDK, though it is completely possible to unbundle it as a standalone class library. JFC, on the other hand, is fully beans-compliant and has employed an efficient event model that results in prominent performance improvement. Migration of an existing AWT-based application using the JDK 1.1 delegation event model to a JFC-based application would be trivial. But rewriting a 1.0-based GUI application to JFC would require structural changes on the application code. Furthermore, the learning curve of JFC is not necessarily a smooth one.
As you have seen, both toolkits have their own advantages and disadvantages. If you consider pluggable look and feel an important feature for your application, or if you need the flexibility and scalability of a MVC architecture in your object-oriented application development, there isn't much reason for you to hesitate -- JFC is an obvious choice and worth the learning cost. If, however, you simply want to develop a quick front-end prototype or a relatively small scale application, we consider AFC a good choice.
Learn more about this topic
- The AWT Home page has almost everything you need to know about AWT in JDK 1.0 and 1.1
- Overview of the Java UI page, an introductory section to user interface in Java from the book, The Java Tutorial
- JDK 1.1 AWT Enhancements page describes the new features in AWT 1.1 and plan for the future
- JDK 1.1 AWT Event Model page provides details of the new AWT event model
- JDK 1.1 Lightweight UI Framework page focuses on the peer-based heavyweight UI problem and the lightweight solution
- JDK 1.1 AWT Documentation provides a guide to, some exmaples of and API reference to the AWT 1.1
- Netscape IFC Developer Central page is a starting point for exploring the IFC, you'll find introduction, documentation, download information, etc.
- IFC Developer's Guide is a complete step-by-step guide to program the IFC
- Microsoft's AFC page provides an overview of and download information for the AFC http://www.microsoft.com/java/resource/afc.htm
- Microsoft SDKJ 2.0 AFC page provides introduction articles, API documentation and samples for the SDKJ 2.0 release
- AFC for JDK 1.0.2 page gives an introduction the AFC 1.0.2 and details its difference from AFC 1.1
- Difference between classes in JDK 1.0.2 compatible AFC and JDK 1.1 compatible AFC page lists the difference of class and method between the two versions of AFC
- JavaSoft's JFC page provides a complete description and download information for the JFC http://www.javasoft.com/products/jfc/index.html
- The Swing Connection, a new JavaSoft Web site providing up-to-date information about JFC's Swing tool set http://java.sun.com/products/jfc/swingdoc-current/
- JFC Frequently Asked Questions provides answers to some frequently asked questions from JavaSoft
- Using the JFC/Swing Packages, a section dedicated to JFC Swing from the book, "The Java Tutorial"
- Java Toolkit Comparison page compares various UI components in AWT, AFC, IFC, and JFC in an easy-to-read form
- JFC and AFC debate creates confusion, demands choices http://www.javaworld.com/javaworld/jw-01-1998/jw-01-afc.html
- Keep listening for upcoming events, an introduction to using the new AWT event model to wire Beans together in a BeanBox