 |
Which Foundation Is for You?
Peter
Haggar Software Engineer, IBM March 1998
Although the Java Abstract Window Toolkit (AWT) is a good
first step toward creating a truly cross-platform GUI class library, the
need is great for a more robust graphical user interface (GUI) class
library that GUI developers can rely on to create leading
applications.
This paper is also available in: Latvian
and Simplified
Chinese.
In order to solve some of AWT's problems, two new class libraries have
emerged: the Java Foundation Classes (JFC) from JavaSoft and the
Application Foundation Classes (AFC) from Microsoft. Which one prevails
will depend on the quality, features, and, ultimately, the acceptance of
each respective library in the industry.
The Java AWT represents Java's first attempt at a cross-platform GUI
class library. Creating a truly cross-platform GUI class library is a
daunting task and not one likely to be perfected the first time around.
Although the AWT is a good first step, the need is great for a more robust
graphical user interface (GUI) class library that GUI developers can rely
on to create leading applications.
Two new class libraries have emerged that are attempting to solve some
of AWT's problems: the Java Foundation Classes (JFC) from JavaSoft and the
Application Foundation Classes (AFC) from Microsoft. Which one prevails
will depend on the quality, features, and, ultimately, the acceptance of
each respective library in the industry.
Introduction One of the
problems with the AWT stems from its design goals. The goal of the AWT is
a cross-platform GUI library that uses the native windows and controls on
the application's run-time platform. Implementing a library using the
native windows and controls has its benefits. Since it uses native
controls, the AWT provides a familiar look and feel to the applet or
application, no matter which platform the code is running on. However,
there are some drawbacks to this approach. The most notable drawback is
referred to as the "lowest common denominator" problem. Since the AWT is
written using native system windows and controls, the functionality is
minimal since it has to span multiple platforms. This is because the
interface represents the common services that can be used across the many
platforms Java supports. If a feature is to be included in the AWT that is
not on all platforms the AWT supports, the AWT must provide that support
via an emulation layer. This emulation layer is necessary if the promise
of "Write Once, Run Anywhere" is to be realized.
The industry recognized the problems related with the native, or
peer-based, window toolkit strategy employed by the AWT. Some leading
industry vendors set out to solve this problem with their own class
libraries. Two Java class libraries emerged from this work: Netscape's
Internet Foundation Classes (IFC) and Microsoft's Application Foundation
Classes (AFC).
IBM, Netscape, and JavaSoft agreed to work together and leverage
Netscape's IFC technology (available since 12/11/96) to produce the JFC.
This cooperation between leading industry partners thrust JFC to the
forefront in the GUI class library battle. The two foremost GUI class
libraries are now the JFC from JavaSoft and the AFC from Microsoft.
Background of AFC and
JFC April 2, 1997, was a big day for Java GUI class
libraries. Both Microsoft and JavaSoft announced competing libraries
during the JavaOne developer conference in San Francisco,
California. Microsoft announced the availability of a preview release for
AFC. AFC was originally announced in January, but this was the first time
code for it had been delivered. Meanwhile, JavaSoft announced that they
were working with IBM and Netscape to produce the JFC. A preview release
of JFC is available now on JavaSoft's Web site: http://www.javasoft.com.
AFC is available from Microsoft's Web site as part of their SDK 2.0. See:
http://www.microsoft.com/java. Both technologies provide advanced user
interface features and lay to rest the claim that you must "dumb down"
interfaces for cross-platform and Web applications. This "dumbing down"
had been the mantra of some critics of the AWT.
Each of these libraries is written to support what are called peerless,
or windowless, components. This means the user interface controls are
drawn by the library itself, not by the system the application is running
on. The result is that the user interface and behavior of the application
will be the same on any platform the code is running on. Since these
libraries don't use any native windows or controls, but implement them
internally, they are not bound to the user interface features of the
platform.
Some people would also argue that this common look and feel is the
future of user interfaces, and that the AWT style native look and feel is
a thing of the past. I think that as the platform on which you are running
your applications becomes less and less relevant, the common look and feel
employed by AFC and JFC will be the norm. If Java becomes as ubiquitous as
we hope, I would like to see the same user interface and look and feel to
my applications whether I am accessing them from a PC running NT or OS/2,
a Macintosh, a Network Computer (NC), or a Personal Digital Assitant
(PDA).
Microsoft's Application Foundation
Classes When discussing the AFC, many people are referring
to the GUI class library portion. Actually, AFC is a little more than
that. AFC contains the following packages:
- com.ms.ui-user interface controls. (Typically, when people talk
about AFC they are referring to the functionality in this package.)
- com.ms.fx-a graphics package. This package contains Java classes for
the manipulation of graphics, fonts, and text.
- com.ms.ui.event-an event handling package. This package contains
support for the Java 1.1 event model.
- com.ms.ui.resource-resource files. This package contains support for
Win32 resource files in Java applications.
- com.ms.util.cab-CAB files. This package contains support for cabinet
(CAB) file creation and extraction.
Most of the discussion in this section focuses on the user interface
aspects of the AFC.
AFC Overview The AFC class library is a high-level framework
for Java application development. AFC is written entirely in Java, which
means it will run cross-platform on any Java-compliant Virtual Machine,
including browsers. The AFC provides a component model, similar to AWT's,
featuring components, containers, and layout managers.
Two design features of the AFC are the use of lightweight classes and
peerless, or windowless, components. The AFC does not directly extend the
AWT Component class. The AFC designers thought that this class was
too "heavy." So AFC includes its own UIComponent class that
supposedly uses less memory than its AWT Component equivalent. The
decision to not extend the AWT Component class affects AFC's
compatibility with the AWT. See the AFC/AWT
Compatibility section below.
Since AFC components do not use any native code on the system on which
they are running, AFC provides a cross-platform and portable library with
a common look and feel. The look and feel of an AFC application will
remain the same as it is moved to different platforms. The AFC does use
the AWT for base frame and dialog windows. These windows are wrappered
with the AFC's compatibility classes, which are prefixed with
AwtUI . AWT compatibility classes will be discussed in more
detail below.
AFC supports the Win32 resource format, allowing developers to use
existing Win32 resources in AFC Java applications. This support has the
added benefit of providing NLS support in the manner of Win32's support.
AFC supports both the 1.0.2 and the 1.1 event models, albeit in
different ways. AFC applications can only support the event model
supported by the JVM they are using. However, AFC components can use
either the 1.0.2 or the 1.1 event model. AFC components implement both
event models internally. However, the interface is slightly different from
the AWT interface. See AFC
Programmability below.
JavaBeans Support The standard AFC components such as
UIPushButton, UIRadioButton, etc., are not JavaBeans. The JavaBeans
support with AFC is limited to the AwtUI * compatibility
classes. This means that, in order to use AFC components as JavaBeans,
they must be wrappered with these compatibility classes. This limits the
effectiveness of AFC applications in which JavaBean support is required.
AFC User Interface Features AFC provides a solid set of user
interface controls with which Win32 programmers will be familiar. All of
the major Win32 controls are provided as part of the AFC com.ms.ui
package, in addition to a few new features. With the addition of the
AwtUI and UI prefixes, many of the class names
will look familiar to Win32 programmers.
The UI prefix is used for standard AFC user interface
classes. The AwtUI prefix is used to denote the class that
is an AWT compatibility class. This is provided as a means for using an
AFC control in an AWT window. More information on this subject can be
found in the AFC/AWT Compatibility section. Table
1 provides a list of many of the AFC user interface controls and their
AWT-compatible counterparts.
Control |
AFC
Class Names |
AWT
Compatibility Names |
Button |
UIPushButton, UIRadioButton, UICheckButton |
AwtUIPushButton, AwtUIRadioButton, AwtUICheckButton
|
Choice |
UIChoice,
UIList |
AwtUIChoice, AwtUIList |
Menu |
UIMenuButton, UIMenuList, UIMenuItem |
AwtUIMenuList |
Static |
UIText,
UIGraphic, UIItem |
AwtUIText,
AwtUIGraphic |
Edit |
UIEdit |
AwtUIEdit |
Scrollbar |
UIScrollBar |
AwtUIScrollBar |
Bandbox |
UIBand,
UIBandBox |
AwtUIBand,
AwtUIBandBox |
Status |
UIStatus,
UIProgress |
AwtUIStatus, AwtUIProgress |
Tree |
UITree |
AwtUITree |
Viewer |
UIScrollViewer, UIColumnViewer, UISplitViewer, UITabViewer,
UIMarquee |
AwtUIScrollViewer, AwtUIColumnViewer, AwtUISplitViewer,
AwtUITabViewer, AwtUiMarquee |
Tip |
|
AwtUITip
|
Dialog
Box |
UIPropertyPage, UIWizardStep |
AwtUIMessageBox, AwtUIPropertyDialog, AwtUIWizard,
AwtUIFindReplaceDialog |
Table 1. Many of the AFC user interface controls and
their AWT-compatible counterparts.
Some AFC features of which to take note are HotTracking and BandBox.
HotTracking is a feature which enables controls to change their appearance
when the mouse is over them. This lets the user know when the mouse is in
a position to interact with the underlying control. The appearance change
in the control can be in the form of one of the following:
- text change
- background color change
- image change
- control outline change (from flat to raised)
The BandBox control is typically used to create a sizable toolbar. Sets
of controls can be added to a UIBand object; then the UIBand
objects can be added to the bandbox. UIBandThumb objects are then
added to the bandbox, allowing the user to size and position each band.
AFC Layout Managers The AFC adds a number of new layout
managers while supporting most, but not all, of the existing AWT layout
managers. There are AFC equivalents for FlowLayout, BorderLayout, and
GridLayout called-not surprisingly-UIFlowLayout, UIBorderLayout, and
UIGridLayout. There are no equivalents for Card and GridBag layouts.
Therefore, these layouts cannot be used in an AFC container. The new
layout managers added by AFC are BarLayout, FixedFlowLayout,
VerticalFlowLayout, RowLayout, SplitLayout, TabLayout, TabListLayout,
ThreePanelLayout, and TreeLayout.
AFC/AWT
Compatibility Since AFC does not directly extend the AWT
component architecture, developers cannot freely mix AWT and AFC
components in an application. In order to provide compatibility with the
existing AWT, AFC employs what it calls the AWT compatibility classes.
(These are the classes with the AwtUI prefix.) These classes
serve as a bridge between AWT containers and AFC components. In other
words, if you want to include any AFC components in AWT containers (for
example, an AWT Frame) you must use the AwtUI * classes, not
the standard UI * classes. I see this design as a major
drawback to using AFC. See AFC Programmability below for additional
details.
AFC Programmability In
preparation for writing this paper, I installed the Microsoft Visual
Studio and the SDK for Java 2.0 Beta 2. I then wrote some AFC code to get
a look at how the platform was put together and what it had to offer. The
main problem is the fact that AFC does not extend directly from the AWT.
This is a problem when trying to mix AFC and AWT components in the same
container, because this mixing requires the AWT compatibility classes.
This problem makes programming the AFC somewhat non-intuitive. In
addition, since AFC, AWT, and AWT-compatible components cannot be easily
mixed, developers need to be acutely aware of with what type of panel they
are working when coding. The following lists show what is and isn't
allowed when trying to mix AWT components, AFC components, and AWT
compatibility components in AWT containers, AFC containers, and AWT
compatibility containers.
In an AWT container (for example, Panel):
- You can embed standard AWT components (for example, Button).
- You cannot embed standard AFC components. For example, you cannot
include a UIPushButton in an AWT container.
- In order to embed AFC components, you need to use the AWT
compatibility classes. For example, in an AWT container, you would use
an AwtUIPushButton, not a UIPushButton.
In an AFC container (for example, UIPanel):
- You can embed standard AFC components (for example, UIPushButton).
- You cannot embed any standard AWT components (for example, Button).
- You cannot embed any AWT compatibility components (for example,
AwtUIPushButton).
In an AWT compatibility container (for example, AwtUIPanel):
- You can embed standard AFC components (for example, UIPushButton).
- You can embed AWT compatible components (for example,
AwtUIPushButton).
- You cannot embed any standard AWT components (for example, Button).
The major drawback here is that in order to use any AFC components in
any AWT containers, one must use the AWT compatibility classes, not the
standard AFC classes (See Listing 1). When using AFC containers,
developers are limited to only standard AFC components and cannot use any
AWT components (See Listing 2). In addition, when using an AWT Compatible
container, standard AWT components cannot be included (See Listing 3).
I found myself continually going back to the documentation to see if I
were using the correct class. For example, if I wanted to put a button in
a container, did I need to use UIPushButton, AwtUIPushButton, or Button?
Well, that depends on the type of container one is using. This made coding
the AFC particularly irritating. Listing 1: AWT
Container and AWT, AFC, and AWT compatibility components
class AWTButtonDemoPanel extends Panel
{
AWTButtonDemoPanel()
{
Button AWTButton = new Button("AWT button");
AwtUIPushButton AWTUIPushButton = new AwtUIPushButton("AwtUIPushButton");
UIPushButton AFCUIPushButton = new UIPushButton("AFCUIPushButton");
add(AWTButton); //OK...standard AWT component
add(AWTUIPushButton); //OK...AFC button used in AWT wrapper
add(AFCUIPushButton);
//Compile error! Will not compile since AWT Panels don't
//know anything about AFC components
}
}
|
Listing 2: AFC Container and AFC, AWT
compatibility, and AWT components
class AFCButtonDemoPanel extends UIPanel
{
AFCButtonDemoPanel()
{
UIPushButton UIPushButton = new UIPushButton("AFC UIPushButton");
AwtUIPushButton AWTUIPushButton = new AwtUIPushButton("AwtUIPushButton");
Checkbox AWTCheckBox = new Checkbox("AWT Checkbox");
add(UIPushButton); //OK...standard AFC Component
add(AWTUIPushButton);
//Compile Error! Will not compile since UIPanel does not
//support the AwtUI* compatibility classes.
add(AWTCheckBox);
//Compile error! Will not compile since UIPanel does not
//support standard AWT components.
}
}
|
Listing 3: AWT Compatible container and AFC,
AWTUI*-compatible, and AWT components
class AWTCompatibleDemoPanel extends AwtUIPanel
{
AWTCompatibleDemoPanel()
{
UIPushButton UIPushButton = new UIPushButton("AFC UIPushButton");
AwtUIPushButton AWTUIPushButton = new AwtUIPushButton("AwtUIPushButton");
Checkbox AWTCheckBox = new Checkbox("AWT Checkbox");
add(UIPushButton); //OK
add(AWTUIPushButton); //OK
add(AWTCheckBox);
//Compiles OK! However, throws IllegalArgumentException
//at runtime. Parameter to add must be a subclass of
//AwtUIControl.
}
}
|
Another cause for irritation is the event model interface in AFC. For
example, instead of implementing the ActionListener
interface as you would in AWT or JFC, you must implement the
IUIActionListener interface. Instead of overriding the
public void actionPerformed(Action event); method as you
would in AWT or JFC, you override the public void
actionPerformed(UIActionEvent event) method. The same holds true
for the other event classes. All of the AFC event and listener classes are
prefixed with UI . Another weakness is that AFC does not
support the adapter classes. The adapter classes are convenience classes
that the AWT employed in the 1.1 event model to make programming the new
event model easier. None of this is very surprising once you understand
the design of the AFC library, but it makes it annoying to program if you
already know the AWT 1.1 event model.
JavaSoft Java Foundation Classes
(JFC) JavaSoft's JFC has been positioned as the main
alternative to Microsoft's AFC. The battle has been escalated by the fact
that Microsoft has stated that they will not ship the JFC library with
their JVM. This means that for JFC applications to run on Microsoft
Windows platforms, they will need a Windows JVM other than Microsoft's.
JFC was born out of Netscape's work on their IFC library. Sun,
Netscape, and IBM have teamed up to produce the JFC, which will ship with
JDK 1.2. When people speak of JFC, they often are referring only to the
user interface components contained in JFC, commonly referred to as
Swing or SwingSet. JFC contains the following:
- High level UI components-Swing
- 2-D Graphics
- Drag and Drop
- Pluggable Look and Feel
- Accessibility Features
JFC Overview The JFC is designed so that it is a superset of
the AWT. In other words, JFC extends directly from the AWT to add many new
components and services. All of the new components in JFC extend directly
from the AWT Component class. This makes JFC fully compatible with
AWT- based applications.
Two of the JFC design features are equivalent to the design features of
AFC. The JFC uses lightweight classes and peerless, or windowless,
components. Also, it does not use any native code when drawing its
components. This allows JFC to provide a cross-platform and portable
library with a common look and feel. Additionally, JFC provides what is
called Pluggable Look and Feel, which provides the ability to
change the look and feel of an application dynamically.
To run JFC applications, the JDK 1.1.2 or higher is required. Because
of this, JFC supports only the 1.1 event handling model.
JavaBeans Support All JFC components are written as
JavaBeans. This gives developers of JFC applications all the benefits of
JavaBeans with their JFC components.
JFC User Interface Features JFC provides a rich set of user
interface components to enhance GUI applications. All of the existing AWT
components are provided, in addition to many new high-level components. To
distinguish between standard AWT classes and JFC classes, all JFC classes
are prefixed with a "J" . See Table 2 for a list of the new
high-level components.
Tree
View |
Slider |
Menus |
Properites |
List
View |
Styled
Text |
Status
Bar |
AudioGauge |
Table
View |
Font
Chooser |
SpinBox |
MidiPanel |
Toolbar |
Color
Chooser |
ComboBox |
MovieController |
Pane
Splitter |
File
Chooser |
Dropdown
ComboBox |
AudioController |
Tabbed
Folder |
Custom
Cursors |
ProgressBar |
MovieSlider |
Multi-Column list |
Tool
Tips |
Buttons |
|
Table 2. The new high-level components.
One very useful and unique feature of the JFC is the DebugGraphics
option. The DebugGraphics feature is a tool you can use to test whether
your components are being drawn correctly. With DebugGraphics, you can
highlight the component parts in bright red as they are being drawn. This
allows you to view them as they are being drawn and to observe exactly how
all drawing operations are taking place.
Another major user interface feature of JFC is Pluggable Look and
Feel, which provides the ability to change the user interface of a set
of components (for example, all buttons) or the entire application
dynamically at run time. To support this feature, JFC application
developers do not need to subclass the entire JFC component set.
JFC Programmability I downloaded the 1.1.3 version of the
JDK and the JFC code from the JavaSoft Web site and started to program
with it. I used my AWT skills to begin programming in JFC immediately.
Working with existing AWT classes in the JFC was a snap. You simply need
to prefix the class name with a "J" . So, if you want a JFC
button, you code JButton. If you want an AWT button, you simply
code Button. You also don't have to worry about mixing JFC and AWT
components and containers. They all work together seamlessly, making it
easy to mix JFC and AWT code.
JFC Layout Managers JFC supports all of the existing AWT
layout managers and also adds a new one. The new layout manager is called
SpringLayout. The SpringLayout allows you to define which spaces should
change size when a component is sized. The defined spaces are: left
margin, right margin, top margin, bottom margin, width, and height. Each
of these spaces can either be a spring or a strut. A spring is a flexible
space and can grow during sizing. A strut is an inflexible space and,
whenever possible, it does not change size.
JFC/AWT Compatibility JFC was designed to be fully
compatible with the AWT. Therefore, you do not need to concern yourself
with mixing separate Component models. This compatibility will be critical
as people begin to use new JFC applications with existing AWT code.
AFC/JFC Performance Comparison To compare the performance, I
first wrote an application using JFC (see Appendix A). This application
allows you to create a frame window with a panel containing a
user-specified number of buttons. The application measures three aspects
of performance:
- creation time of the frame with the buttons
- layout time of the buttons
- paint time of the buttons
Once I had the application working properly under JFC, I block-copied
the code into Microsoft Visual Studio and converted it to be run with AFC
(see Appendix B). This conversion was very simple and straightforward. The
design of the application did not have to change-only the class names
being used were changed. When I got a clean compile, the AFC program
worked properly the first time. I then had identical applications for both
JFC and AFC with which to run my tests.
Both programs employed identical designs. I overrode the
paintAll() and layout() methods to capture the
paint and layout timings (in the JFC code, I actually overrode
doLayout() since layout() was deprecated for
1.1). The code was compiled and run with the following setup for JFC:
- JDK 1.1.3
- JFC Swing 0.3 developers' preview release
For AFC:
- Microsoft Visual Studio
- SDK for Java 2.0 Beta 2
Before I actually looked at the numbers, I noticed that JFC seemed to
be much faster than AFC. The performance numbers supported this
observation. See Table 3 for the actual numbers. All times were gathered
using the System.currentTimeMillis() call. I ran the
creation time scenario numbers, creating 100 and 500 buttons. The layout
and paint times were both done only for 100 buttons. The numbers are an
average of five samples I took for each test.
All of the performance measurements were generated on an unloaded
133MHz Pentium processor machine with 80MB of memory running Window NT
4.0. In addition, each application was built with the -O option
indicating full optimization of the code.
Activity |
AFC average time in milliseconds |
JFC average time in milliseconds |
Create 100
Buttons |
1,692 |
592.6 |
Create 500
Buttons |
6,895.8 |
3,072.8 |
Layout |
326.4 |
96.2 |
Paint |
478.8 |
382.4 |
Table 3. AFC performance versus JFC performance.
As you can see, JFC easily outperformed AFC in each category-and by a
wide margin. More specifically, JFC performed 185% faster creating 100
buttons, 124% faster creating 500 buttons, 239% faster during layout, and
25% faster painting the buttons.
Both libraries exhibited painting problems and unnecessary multiple
paints and layouts, but I would not expect much more from Beta code.
Improvements will be made to both libraries as time goes by, but JFC has a
clear performance advantage, which AFC will have to work very hard to
match, let alone eliminate.
AFC/JFC Feature Comparison Table 3 is a list of the major
differentiating features between AFC and JFC. I have indicated the feature
and noted the support each library gives the feature. I have then
indicated (in bold CAPS), where appropriate, which library has a
better implementation and, therefore, a competitive advantage based on the
implementation of the feature.
Feature |
AFC |
JFC |
100% Pure
Java |
Yes |
Yes |
Pluggable
L&F |
No |
YES |
Peerless
Components |
Yes |
Yes |
Lightweight Comp |
Yes |
YES |
JavaBeans
support |
Limited |
FULL |
1.0 Event
Model |
YES |
No |
1.1 Event
Model |
Yes |
YES |
Drag/Drop |
No |
YES |
Printing |
No |
YES |
Win32
Resource files |
YES |
No |
2D
Graphics |
Yes |
Yes |
AWT
Compatibility |
Limited |
EXCELLENT |
Programmability |
Fair |
EXCELLENT |
Performance |
Poor |
GOOD |
Table 3. Comparison of AFC and JFC features.
And the Winner
Is.... Based on the facts uncovered during my examination of
these two class libraries, JFC is the clear winner. JFC is better
designed, has more features, and is easier to use than AFC. Each one has a
few features the other does not, but AFC lacks the more important features
that JFC provides. Strong AWT compatibility, Drag/Drop, and Printing are
three features AFC does not have and needs in order to be considered a
serious contender.
In areas in which they both provide the same feature, the JFC
implementation and support are typically much better than AFC. For
example, JFC does a much better job with JavaBeans, general
programmability, and the 1.1 event model. In addition, the performance of
the JFC was far superior to AFC, giving the JFC a big edge in this
important category.
JFC is a more solid foundation on which build Java applications. It was
clear in using JFC that the designers intended little to no impact on
current AWT programmers moving to the JFC. Appendix
A
//JFC Performance measurement application
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
class JFCButtonFrame extends Frame implements ActionListener
{
private JButton repaintButton;
public JFCButtonFrame(JFCPerfFrame perfFrame, int numButtons)
{
setTitle("JFC Button Panel");
setLayout(new BorderLayout());
JFCButtonPanel buttonPanel = new JFCButtonPanel(perfFrame, numButtons);
add(buttonPanel, "Center");
JPanel timePanel = new JPanel();
repaintButton = new JButton("Repaint");
repaintButton.addActionListener(this);
timePanel.add(repaintButton);
add(timePanel, "South");
class JFCButtonFrameAdapter extends WindowAdapter
{
public void windowClosing(WindowEvent event)
{
dispose();
}
}
addWindowListener(new JFCButtonFrameAdapter());
}
public void actionPerformed(ActionEvent event)
{
if (event.getSource() == repaintButton)
{
paintComponents(getGraphics());
}
}
}
class JFCButtonPanel extends JPanel
{
private JFCPerfFrame perfFrame;
public JFCButtonPanel(JFCPerfFrame f, int numButtons)
{
perfFrame = f;
setLayout(new FlowLayout());
for (int i=0; i
|
Appendix B
//AFC Performace measurement application
import com.ms.ui.*;
import com.ms.fx.*;
import com.ms.ui.event.*;
import java.awt.*;
import java.awt.event.*;
class AFCButtonFrame extends AwtUIFrame implements IUIActionListener
{
private UIPushButton repaintButton;
public AFCButtonFrame(AFCPerfFrame perfFrame, int numButtons)
{
setTitle("AFC Button Panel");
setLayout(new UIBorderLayout());
AFCButtonPanel buttonPanel = new AFCButtonPanel(perfFrame, numButtons);
add(buttonPanel, "Center");
UIPanel timePanel = new UIPanel();
repaintButton = new UIPushButton("Repaint", UIPushButton.RAISED);
repaintButton.addActionListener(this);
timePanel.add(repaintButton);
add(timePanel, "South");
}
public void actionPerformed(UIActionEvent event)
{
if (event.getSource() == repaintButton)
{
paintComponents(getGraphics());
}
}
public boolean handleEvent(Event evt)
{
switch (evt.id)
{
case Event.WINDOW_DESTROY:
dispose();
return true;
default:
return super.handleEvent(evt);
}
}
}
class AFCButtonPanel extends UIPanel
{
private AFCPerfFrame perfFrame;
public AFCButtonPanel(AFCPerfFrame f, int numButtons)
{
perfFrame = f;
setLayout(new UIFlowLayout());
for (int i=0; i
|

|
 |