tool \'tül \ n: an instrument or apparatus necessary in the practice of a vocation or profession
Java's Abstract Windowing Toolkit (awt) package contains classes with which you can interact with the user of your programs. Though the awt classes are nice, there are no bells and whistles. This chapter is dedicated to providing you with those bells and whistles to extend the visual beauty of your intranet applications.
The main thrust of this chapter is to introduce you to the interfaces and classes with which you can enhance your user interface. You will use these classes in your programs mainly to construct visual elements to enhance the look and feel of your Java programs.
Before you dig into the classes, however, let's look at a little 3-D theory.
Two features that I like to use in my GUI applications are 3-D panels and group boxes. They give a nice touch to any input screen and can transform a boring screen into one bubbling with personality.
Core Java cannot create these hip containers, however. Enter the JifPanel class. With this class, you can create an array of interesting effects with the greatest of ease. Figures 11.1 and 11.2 show the different things a JifPanel can do.
Figure 11.1 : The versatile JifPanel.
Figure 11.2 : The JifPanel behaving like a group box.
| Note |
JIF stands for Java Intranet Framework. As you'll see in Chapter 12, "Putting Them All Together," all of the classes you've talked about, including those in this chapter, are packaged together into the Java Intranet Framework, or JIF. You will see other objects that start with JIF. |
The JifPanel class is covered
in greater detail later in this chapter. For now, let's discuss
the interface behind the JifPanel
class: Effects.
| Note |
Figure 11.1 represents the output of one example program on the CD-ROM. The program is called PanelTester. |
| Note |
Figure 11.2 represents the output of one example program on the CD-ROM. The program is called GroupBoxTester. |
The Effects interface extends the components' look and feel. The Effects interface only consists of constants defining the styles available. Only the JifPanel class implements this interface.
The Effects styles are divided into three areas:
Let's examine each set of styles individually.
The first set of styles is the border styles. These dictate how a component will render its border. The available styles are
Each of these styles is represented in Figure 11.1. Listing 11.1 shows the actual definitions of these styles.
Listing 11.1. The border styles available in the Effects interface.
public final static int NONE = 0;
public final static int FLAT = 1;
public final static int GROOVED = 2;
public final static int LOWERED = 4;
public final static int ROUNDED = 8;
public final static int RAISED = 16;
public final static int RIDGED = 32;
public final static int CAPTION = 64;
Notice that the styles are offsets in a bit-mapped field. That means that they can be added together to combine the effects. Some effects do not warrant combining and are pointless. For instance, you won't want to combine GROOVED with RIDGED, or LOWERED with RAISED. Sometimes you might want to combine RAISED and ROUNDED, however.
Text effects, the second set of styles defined by the Effects interface, dictate the way a component will draw the text it contains. Four styles are available:
Each of these styles is represented in Figure 11.1. Listing 11.2 shows the actual definitions of these styles.
Listing 11.2. The text styles available in the Effects interface.
public final static int TEXT_NORMAL = 0;
public final static int TEXT_LOWERED = 1;
public final static int TEXT_RAISED = 2;
public final static int TEXT_SHADOW = 3;
Unlike the border styles, these styles increment sequentially. They cannot be combined.
The third and final style set is the text placement styles. While not styles so much as locations, they indicate one aspect of the display of the text. Three styles are available:
Again, please refer to Figure 11.1. Each of the preceding styles is demonstrated in the example. Listing 11.3 shows the actual definitions of these styles.
Listing 11.3. The text placements available in the Effects interface.
public final static int CENTER = 0;
public final static int LEFT = 1;
public final static int RIGHT = 2;
Like the text styles, these placement styles increment sequentially. They also cannot be combined.
The most important user interface class you'll develop is the JifPanel class, which implements the Effects interface and provides many 3-D effects along with some special features. To fully explain the JifPanel, this section discusses its design and then covers some of the constructors and the source code.
The JifPanel extends Java's Panel class. As you know, the Panel class extends the Container class, which allows the Panel to hold or contain other components. You can assemble this panel of components, along with other panels of components, to construct a complete user interface for an application.
The following is the declaration of the JifPanel class:
//****************************************************************************
//* JifPanel &n bsp; *
//****************************************************************************
public class JifPanel
extends Panel
implements Effects
The JifPanel implements the Effects interface. As the Effects interface only contains constants, it imposes no structure on the JifPanel class. All of the constants available in Effects are available to the JifPanel, however.
You can construct a JifPanel in several ways. You can use it as a regular Java Panel by creating it with no arguments:
JifPanel myPanel = new JifPanel();
You can create one that has a specific type of border:
JifPanel myPanel = new JifPanel( Effects.RAISED );
You can specify a fixed size for your panel:
JifPanel myPanel = new JifPanel( Effects.RAISED, 100, 100 );
You can create one that contains a text string:
JifPanel myPanel = new JifPanel( "JIF Rules!!" );
Finally, you can create one with a cool border that is of a fixed size with text inside:
JifPanel myPanel = new JifPanel( Effects.RAISED, 100, 100, "JIF Rules!!" );
Hopefully there are enough options from which you can choose. If there aren't, you can always subclass the JifPanel and create your own extensions.
Once again, refer to Figure 11.1 for a gander at the different border, text, and text placement styles available for a JifPanel.
If you're at all like me, you are probably ready to look at some source code. I'm sure you're wondering how to create those cool 3-D border and text effects. It doesn't take smoke and mirrors or a degree from a clown college. It's quite simple, and I'll show you how.
A 3-D border around a component is one of the easiest and most professional looking effects to program. Drawing a 3-D border around any component requires two details: border style and border thickness.
The first step is to decide on the style of the 3-D border you want to draw. The two basic styles are lowered and raised.
A lowered border is a border that looks sunken or lower than the area that contains it. Figure 11.3 illustrates the concept of a lowered border.
Figure 11.3 : A lowered border.
To make an object appear as if it is sunken, you need to create what appears to be a shadow. To do this, the upper and left side of your component should be darker than the lower and right side. In Figure 11.3, a 10¥10 grid represents a 10¥10 grid of pixels. The dark pixels represent the area in the shadow. The clear, or white, pixels represent the area that is lit up. If you squint your eyes and look at the figure, it will look lowered into the book.
A raised border is a border that looks as if it is coming off of the screen. This is a common look for buttons and other clickable objects. Figure 11.4 illustrates the concept of a raised border.
Figure 11.4 : A raised border.
To make the object appear as if it is raised, you need to create a shadow at the bottom of the object. To do this, the upper and left side of your component should be lighter than the lower and right side. In Figure 11.4, a 10¥10 grid represents a 10¥10 grid of pixels. The dark pixels represent the area in the shadow. The clear, or white, pixels represent the area that is lit up. Again, if you squint your eyes and look at the figure, it will look raised from the book.
The grooved and lowered border types are worth mentioning. You can create group boxes with these two borders. Figure 11.5 illustrates the method for creating a grooved and lowered border.
Figure 11.5 : A grooved border.
Figure 11.6 illustrates the method for creating a lowered border.
Figure 11.6 : A lowered border.
The last detail you need before you dig into the code is the thickness of the border. The thickness of the border is the width of the border in pixels. The default thickness for a JifPanel is two pixels.
Thicker borders look odd, and borders thinner than two pixels almost defeat the purpose of the 3-D effect.
The drawFrame() method in the JifPanel class is responsible for drawing the 3-D border. The source code for that method follows:
//****************************************************************************
//* drawFrame & nbsp; *
//****************************************************************************
public void
drawFrame( Graphics g )
{
int i, j, offset = 0, rounded = 0;
Dimension bounds = size();
if ( isStyleSet( CAPTION ) )
{
// Fix up for font...
FontMetrics fm = g.getFontMetrics();
offset = fm.getHeight() / 2;
}
for ( i = 0, j = 1; i < thickness; i++, j += 2 )
{
if ( i != 0 )
rounded = 0;
else
if ( isStyleSet( ROUNDED ) )
rounded = 1;
if ( isStyleSet( RAISED ) ||
( isStyleSet( RIDGED ) && ( j <
thickness ) ) ||
( isStyleSet( GROOVED ) && ( j >
thickness ) ) )
g.setColor( Color.white );
else
g.setColor( Color.gray );
// Draw top line...
g.fillRect( i + rounded,
i + offset,
bounds.width - ( 2 * ( i + rounded ) ),
1 );
// Draw the left side...
g.fillRect( i,
i + rounded + offset,
1,
bounds.height - ( 2 * i + 1 + rounded ) - offset );
if ( isStyleSet( RAISED ) || isStyleSet(
FLAT ) ||
( isStyleSet( RIDGED ) && ( j < thickness ) ) ||
( isStyleSet( GROOVED ) && ( j >
thickness ) ) )
g.setColor( Color.gray );
else
g.setColor( Color.white );
// Draw the bottom line...
g.fillRect( i + rounded,
bounds.height - ( i + 1 ),
bounds.width - ( 2 * ( i + rounded ) ),
1 );
// Draw the right side...
g.fillRect( bounds.width - ( i + 1 ),
i + rounded + offset,
1,
bounds.height - ( 2 * i + 1 + rounded )
- offset );
}
}
The drawFrame() method draws the border in a loop fashion. Each run through represents one pixel from the thickness of the border. If the border thickness was set to two, the default, this loop would be performed twice.
This method first draws the upper and left lines of the border. It then swaps colors and draws the lower and right lines of the border. Each time through the loop, it thickens the border by one pixel.
Ridged and grooved borders are a little bit more complex. They swap colors halfway through the loop, giving them a walled or grooved look.
Drawing 3-D text isn't nearly as complicated as drawing the 3-D borders. Making the text look lowered or raised is very simple. The following source code is for the JifPanel method drawtext():
//****************************************************************************
//* drawtext &n bsp; *
//****************************************************************************
public void
drawtext( Graphics g )
{
Color oldColor = g.getColor();
int xx = 0, yy = 0;
FontMetrics fm = g.getFontMetrics();
Dimension bounds = size();
// Decide where to place the text...
if ( !isStyleSet( CAPTION ) )
{
switch ( textPlacement )
{
case CENTER:
xx = ( bounds.width / 2 ) - ( fm.stringWidth( text ) / 2 );
yy = ( bounds.height / 2 ) - ( fm.getHeight() / 2 );
break;
case LEFT:
xx = thickness + TEXT_OFFSET;
yy = ( bounds.height / 2 ) - ( fm.getHeight() / 2 );
break;
case RIGHT:
xx = bounds.width - thickness - TEXT_OFFSET -
fm.stringWidth( text );
yy = ( bounds.height / 2 ) - ( fm.getHeight() / 2 );
break;
}
}
else
{
int spacer = fm.charWidth( 'i' );
xx = thickness + TEXT_OFFSET + spacer;
yy = 0;
// Fill a rectangle in the bounding space of the string...
g.setColor( getBackground() );
g.fillRect( xx, yy,
fm.stringWidth( text ) + ( spacer * 2 ),
fm.getHeight() );
xx += spacer;
}
// Adjust for drawString weirdness...
yy += fm.getHeight() - fm.getDescent() - 1;
if ( textStyle == TEXT_LOWERED )
{
// Draw highlight to right and below text
g.setColor( Color.white );
g.drawString( text, xx + 1, yy + 1 );
}
if ( textStyle == TEXT_RAISED )
{
// Draw highlight to left and above text
g.setColor( Color.white );
g.drawString( text, xx - 1, yy - 1 );
}
if ( textStyle == TEXT_SHADOW )
{
// Draw shadow to right and below text
g.setColor( Color.gray );
g.drawString( text, xx + 1, yy + 1 );
}
g.setColor( Color.black );
g.drawString( text, xx, yy );
// Restore the old color...
g.setColor( oldColor );
}
The first half of this method sets the starting point for the text to be drawn. Based on the text placement, the x and y coordinates for drawing the text are calculated. For CENTER, the text is centered in the width of the component. For LEFT, the text is offset by five pixels. For RIGHT, the text is offset by five pixels from the right side of the component.
Now, if the CAPTION style is set, you need special processing because the CAPTION style requires a background to be drawn before the text is drawn. The method calculates the size of the rectangle that will be drawn. This rectangle will be a little wider than the text itself but exactly the same height.
The second half of this method draws the specialty text, which is the lowered, raised, and shadowed text styles. These effects are achieved simply by drawing a copy of the text in white and then drawing the text again in black, offset by one pixel. This offset is important. If you offset up and over one, you get that lowered look. If you offset down and to the right, you get a raised look. The shadowed text is just like the lowered text, but the background color is gray instead of white.
Finally, you restore the old color to the Graphics canvas. Others may depend on this color being there. If you don't do this, subsequent drawing of other components may be colored incorrectly.
Another feature of the JifPanel
class is that you can tab between the components contained in
the panel. This behavior of tabbing from one component to another
is a GUI standard that many have come to feel comfortable with.
But creating the effect is quite simple as you'll see.
| Note |
As of the JDK v1.0.2 for Windows NT and Windows 95, this tabbing feature was not available and has been reported as a bug. I have added it here for this reason. If later versions of the JDK support tabbing, this feature of the JifPanel will no longer be necessary. |
You took over the event handler in our JifPanel class and looked for the pressed Tab key. The Tab key's value is 9, and you created a constant called TAB_KEY to hold that value:
final static public int TAB_KEY = 9;
The instance variable called currentPos keeps track of the component that currently has the focus.
When you press a key on the keyboard, a KEY_PRESS event is generated. Capturing keystrokes is as easy as overriding the handleEvent() method.
When you press the Tab key, you check to see if the target of the key press is a component. If it is, you jump the focus to the component directly following the target in the creation order. If you hold down the Shift key when you press the Tab key, you jump backward one component. This handles the jumping from the Tab key.
One last thing you need to do is keep track of mouse clicks. When
the user clicks the mouse on a component, that component receives
the focus and then generates a GOT_FOCUS
event. You capture this event as well and set your internal pointer,
currentPos, to point at this
component.
| Caution |
As of the JDK v1.0.2 specifically on the Windows NT and Windows 95 platform, components did not properly generate the GOT_FOCUS and LOST_FOCUS events when they received and lost the focus. This appears to be a bug in the implementation, but it might turn out that some components never will generate these events. In any case, the behavior of tabbing can be affected by the user clicking on a component out of the tab order because of this bug. You might see the Tab key cause the cursor to jump around. |
The following is the source code for the handleEvent() method of JifPanel:
//****************************************************************************
//* handleEvent   ; *
//****************************************************************************
public boolean
handleEvent( Event event )
{
// Look for certain events to move the focus...
if ( ( event.id == Event.GOT_FOCUS || event.id == Event.ACTION_EVENT )
&& event.target instanceof Component )
{
// Set the focus to this comoponent...
setFocus( ( Component )event.target );
}
// Handle tabs nicely...
if ( event.id == Event.KEY_PRESS && event.key == TAB_KEY )
{
if ( event.target instanceof Component )
{
if ( !event.shiftDown() )
focusForward( ( Component )event.target );
else
focusBackward( ( Component )event.target );
}
// I handled it...
return( true );
}
// I don't want this...
return( super.handleEvent( event ) );
}
The two methods, focusForward() and focusBackward(), move the focus to the next or previous component, respectively. These two methods skip Labels and disabled components. You don't want an inert object to get the focus; you'll never get the focus back.
The last feature of the wonderful JifPanel is that it can generate a SQL statement suitable for sending to a database. This feature only works when the panel itself contains other components that implement the SQLFactory interface, however. (See Chapter 10, "Database Classes," for more information on SQLFactory.)
When you request a JifPanel to generate a SQL statement for the components contained within, the JifPanel queries each component for some information. First and foremost, the panel needs to know if the component implements the SQLFactory interface. If it does not, there is really no way to generate SQL for that component. To see whether a class implements an interface, the operator instanceof returns true. The following code shows this in action:
// Is this a non-mundane component?
if ( cList[ i ] instanceof SQLFactory )
{
// Get the SQL statement...
String sql = ( ( SQLFactory )cList[ i ] ).generateUpdateSQL( false );
}
The cList is an array of the components contained within the panel. You check each element in the array with the instanceof operator. If the component implements the SQLFactory interface, you then can call its generateUpdateSQL() method by casting the component array variable to that of a SQLFactory object.
In any case, the JifPanel will return complete INSERT or UPDATE SQL statements if filled with components that implement the SQLFactory interface. These strings are suitable for sending directly to your database.
Five classes descend from the JifPanel class: CalendarPanel, ImagePanel, JifLabel, JifTabPanel, and StatusBar. Let's look at each one in detail.
As the name implies, the CalendarPanel represents a calendar. (See Figure 11.7.) The calendar starts at a certain month and can be moved forward or backward one month at a time. Each day is implemented as a button that the user can press.
Figure 11.7 : The CalendarPanel as used in the CalenderTester program.
When the user presses one of the days, an ACTION_EVENT is sent to the parent of the object. This event contains the date selected in a Java Date object as the argument.
Listing 11.4 is from the CalendarTester program. It creates and displays a CalendarPanel object for you to play with. The complete source code is available on the CD-ROM. The output of the CalendarTester program is shown in Figure 11.8.
Figure 11.8 : The output of the CalenderTester program.
Listing 11.4. A code snippet from the CalendarTssester program.
//****************************************************************************
//* CalendarTester &n bsp; *
//****************************************************************************
public
CalendarTester()
{
super( "Calendar Tester" );
// Let's use a nicer font...
setFont( new Font( "Helvetica", Font.PLAIN, 14 ) );
// Create the calendar...
myPanel = new CalendarPanel();
add( "Center", myPanel );
// Pack it up!
pack();
show();
}
//****************************************************************************
//* action &nbs p; *
//****************************************************************************
public boolean
action( Event e, Object a )
{
// Was this my boy?
if ( e.target == myPanel )
{
// Tell the user!
MessageBox mb = new MessageBox( this, "Hey!",
"You picked " + ( ( Date )a ).toString() );
mb.show();
return( true );
}
return( false );
}
}
This program simply creates a CalendarPanel object and adds it to the center of its BorderLayout. The ACTION_EVENT event tells you that someone clicked a button. So, you've added an action() method to receive these ACTION_EVENT events. When the events are received, you verify that they were generated from your CalendarPanel. If all checks out, you notify the user that a day has been picked with another cool class-the MessageBox. This class is discussed later in this chapter.
The ImagePanel class is an extension of the JifPanel class that loads an image and resizes itself to the size of the image. This is useful for many applications, including in the JifDialog descendant class MessageBox. Later in this chapter you'll see more about the MessageBox class.
ImagePanels are constructed in the following manner:
ImagePanel ip = new ImagePanel( "c:\\image.gif", 15 );
or
ImagePanel ip = new ImagePanel( "c:\\image.gif );
Each constructor takes as the first argument the name of the graphic file to load. Whatever image types Java supports, the ImagePanel also supports. Currently, only GIF and JPEG image formats are supported.
The second, optional, argument allows to you specify a pixel border between the edge of the panel and where the image is drawn. The default is five pixels.
One shortcoming of Java's Label class is that it can only nicely display a single line of text. If you put a second line in there, separated by a line feed perhaps, you get an ugly display on the screen. The JifLabel fills this niche. It creates a multiline label in an easy manner.
Another Java book that includes an excellent multiline label class is on the market, so I tried to do one better. The other multiline label class depends on when you created the components and manages the size of the text. Ugh! While elegant and visually pleasing, it was too much work. I like the KISS principle of software construction: Keep It Simple, Stupid. On that note, I present the entire source code for the JifLabel:
//****************************************************************************
//* JifLabel &n bsp; *
//****************************************************************************
public class
JifLabel
extends JifPanel
{
//****************************************************************************
//* Constructors &nbs p; *
//****************************************************************************
public
JifLabel( String s )
{
// Stuff the string in a tokenizer to get at each line...
StringTokenizer st = new StringTokenizer( s, "\n" );
int tCount = st.countTokens();
// Make a grid...
setLayout( new GridLayout( tCount + 2, 1, 0, 0 ) );
// Leave some space...
add( new Label( " " ) );
// Make each line a new label and add to layout...
for ( int i = 0; i < tCount; i++ )
add( new Label( st.nextToken() ) );
// Leave some space...
add( new Label( " " ) );
}
}
The JifLabel is extremely simple. First, you break the string into bits on the new-line (\n) boundaries. Using Java's StringTokenizer makes this task very simple.
Second, you store the number of lines of text in the variable tCount to create a new layout for the label. You create a grid layout that is tCount plus two rows high and one column wide. The extra two rows are spacer rows to make the JifLabel look even nicer.
Now you are ready to construct the actual label. Add a spacer label at the top. Next, spin through a loop and take out each line from the tokenizer. Each line you take out is added to the layout as a new Label. Lastly, add a new spacer to the bottom.
Pretty simple, eh? I think you'll like the results considering the code that created it. Figure 11.9 shows a sample JifLabel in the output of the LabelTester program.
Figure 11.9 : The output of the LabelTester program.
The following code is part of the LabelTester program so you can see how easy it is to create JifLabels:
public
LabelTester()
{
super( "Label Tester" );
String labelString =
"Hi, this is the versatile JifLabel!\n" +
"It is a multi-line label that was\n" +
"very easy to program!\n\n" +
"What do you think?";
JifLabel myLabel = new JifLabel( labelString );
myLabel.setFont( new Font( "Helvetica", Font.BOLD, 14 ) );
add( "Center", myLabel );
// Pack it up!
pack();
show();
}
Another shortcoming of the stock Java widgets is the lack of a tabbed panel, or folder widget. This widget presents information one sheet at a time. This new metaphor is common in Microsoft Windows and is becoming popular on other platforms as well.
Sun Microsystems, Inc. noted that this would catch on, so they provided the CardLayout layout manager. This layout presents a stack of components with only one component visible at a time. You must bring one card in the stack to the top to view it.
The JifTabPanel class has used this layout. This class provides a simple Microsoft Windows-like tabbed panel for your applications. This simple device uses a BorderLayout for its components.
The JifTabPanel class consists of a JifPanel, a row of tabs from which to select in the North layout, and a CardLayout of components in the center layout. The JifTabPanel is limited in that it only provides a single layer of tabs. (See Figure 11.10.)
Figure 11.10 : The output of the TabTester program.
The following code is from the TabTester program. You can see how easy it is to use:
public
TabTester()
{
super( "Tab Tester" );
// Create a Tab panel...
JifTabPanel myPanel = new JifTabPanel();
// Add some panes to it...
myPanel.addPane( "Pane 1",
new JifPanel( JifPanel.RAISED, 275, 375, "Panel 1" ) );
myPanel.addPane( "Pane 2",
new JifPanel( JifPanel.RAISED, 275, 375, "Panel 2" ) );
myPanel.addPane( "Pane 3",
new JifPanel( JifPanel.RAISED, 275, 375, "Panel 3" ) );
myPanel.addPane( "Pane 4",
new JifPanel( JifPanel.RAISED, 275, 375, "Panel 4" ) );
myPanel.addPane( "Pane 5",
new JifPanel( JifPanel.RAISED, 275, 375, "Panel 5" ) );
// Add to the center...
add( "Center", myPanel );
// Pack it up!
pack();
show();
}
The final JifPanel extension is the StatusBar class, the area at the bottom of our model intranet application (see Chapter 7, "A Model Intranet Application," for more information). You can use the StatusBar class to display messages to the user. If you leave it at its default value, it simply says "Ready." You can set it to anything you want, however.
The StatusBar class has only a single method useful to your program: the clear() method. This method sets the text to nothing so the status bar shows nothing. It relies on the setText() method of the parent class, which is used to change the text displayed in the status bar.
The next major user interface class is the JifDialog class. This class extends the basic Java Dialog class and adds a few cool behaviors:
You would have to implement these three features for each dialog box you create, so why not put them in a centralized base class? That's what the JifDialog class is-a centralized location.
A method also included in this class, center(),
centers the dialog box within either the screen or the window
that owns it.
| Note |
The Windows NT/95 JDK v1.0.2 has a bug that causes all windows to report their x,y location as 0,0. This makes it impossible to center the dialog box within the parent window. Therefore, the parent centering will not work until the bug is fixed or used on another platform. |
Three classes descend from JifDialog: MessageBox, ResponseDialog, and PickList. All of these classes, except PickList, are demonstrated in the DialogTester program. The source code for this program is shown in Listing 11.5.
Listing 11.5. The DialogTester program.
//****************************************************************************
//* DialogTester &nbs p; *
//****************************************************************************
public class
DialogTester
extends Frame
{
//****************************************************************************
//* Members &nb sp; *
//****************************************************************************
ResponseDialog myDialog;
//****************************************************************************
//* main *
//****************************************************************************
public static void
main( String args[] )
{
new DialogTester( args );
}
//****************************************************************************
//* Constructor   ; *
//****************************************************************************
public
DialogTester( String args[] )
{
super( "Dialog Tester!" );
JifPanel p = new JifPanel( Effects.LOWERED );
p.setLayout( new FlowLayout() );
p.add( new Button( "Plain MessageBox" ) );
p.add( new Button( "Info MessageBox" ) );
p.add( new Button( "Stop MessageBox" ) );
p.add( new Button( "Exclamation MessageBox" ) );
p.add( new Button( "Question MessageBox" ) );
p.add( new Button( "ResponseDialog" ) );
// Add the timer panel to the frame...
add( "Center", p );
// Pack the panels...
pack();
show();
}
//****************************************************************************
//* action &nbs p; *
//****************************************************************************
public boolean
action( Event event, Object arg )
{
MessageBox mb = null;
if ( arg.equals( "Plain MessageBox" ) )
{
mb = new MessageBox( this, "Plain MessageBox",
"This is a plain message box" );
}
else if ( arg.equals( "Info MessageBox" ) )
{
mb = new MessageBox( this, "Info MessageBox"