Chapter 8 -- The Order Entry System: Entry Fields,
Labels, and Validation
Chapter 8
The Order Entry System: Entry Fields,
Labels, and Validation
CONTENTS
This chapter is going to cover much information. First, it further
explores the concepts of containers in the Java AWT. It covers
how to implement the different container types and how they interact
with each other. Remember, containers are components which function
to contain other components. The different containers available
allow you to create stand-alone window applets, and also clean
up the appearance of the Order Entry System. The chapter also
describes pop-up dialog boxes and the means to incorporate them
into your applets.
Second, the chapter covers the five different AWT layout managers.
These allow you, the programmer, to place your components in containers
in an orderly fashion while you still maintain platform independence.
The five layout managers are: FlowLayout,
BorderLayout, CardLayout,
GridLayout, and GridBagLayout.
The GridBagLayout is the
layout manager that is used to reorganize the Order Entry System
applet panel later in this chapter.
The first concept to understand is the idea that containers are
components. Containers are components and they also hold components.
Containers can hold other containers. When you embed containers
inside of containers, you are subdividing the applet (or application)
display area. By doing this, you can apply different layouts to
each separate subdivision of the display face.
It is beneficial to have different groups of components laid out
in different ways. This way, you don't have to settle on a layout
that is mediocre for all of your components. Instead, you can
choose the layout that is best and apply that to each subdivision
(container) of the applet face. This process is how you create
appealing interfaces and still maintain platform independence.
This concept is covered again when you add to the Order Entry
System later on in this chapter.
The simplest containers are panels. In terms of simplicity, they
are to containers what labels are to interface components. But
in terms of power, the Panel
class is infinitely more powerful and useful than the Label
class.
Panels are AWT components that hold other components. By themselves,
panels are basically nothing. One usually expects a container
as known in the real world to have some visible form; however,
panels are invisible. They have no visible boundaries or characteristics
to visually separate them from other components or containers.
If you try to display an empty instance of the Panel
class you get what you expect when you display something that
is made completely of nothing: nothing. In a nutshell, panels
are classes whose sole purpose is to group other components together.
To declare a panel, use the following code:
Panel APanel = new Panel();
To insert components, including other containers, into a panel,
use the same method that you use when inserting components onto
applet faces, the add method.
To insert a component named SomeComponent
into your new panel declared above, use the following code:
APanel.add(SomeComponent);
The add method takes an instance
of the Component class as
a parameter. Each container, including Applet,
has an add method. This is
inherited from the java.awt.Container
class found in the AWT package. To insert a component into another
container, you should do what you did above, call the container's
add method and include the
component as a parameter. To simply insert something onto the
main panel, such as you do with the Applet
class, simply add(SomeComponent)
without specifying it as a method of another container.
The add method has so far
appeared in two seemingly unrelated sections of the book (inserting
components into an applet and also into a container). This should
raise some questions in your head. If you look back at the inheritance
hierarchy of the java.awt.Applet
class in Chapter 5, "Writing a Java
Applet: The Order Entry System," you see that the Applet
class is actually a subclass of the Panel
class. This is why the chapter refers to the applet face as the
"applet panel." This is because applets themselves are
actually specialized Panels
that have included more methods so they are able to be executed
in an html document by a Web browser. Here is the inheritance
path of the java.awt.Applet
class in Figure 8.1. Pay attention to the fact that applets are
themselves subclasses of the Panel
class.
Figure 8.1: The inheritance path of the java.awt.Applet class
Later, the chapter covers the concept of layout managers in the
AWT. These layout managers can be applied to set the layout inside
of Panels and other containers.
Frames are another subclass of java.awt.Container.
They share the same two major operators: add
and a method to be named later (sounds like baseball), and also
do quite a bit more. Frames are the means by which you can incorporate
stand-alone windows into your Java applets or create windowing
Java applications.
Note: |
java.awt.Frame and java.awt.Dialog (covered in the next section) are both actually subclasses of the Window class. The Window class is the means to implement a stand-alone window in Java. However, it is non-functional
for our purposes. While the Panel class can be readily embedded inside of other containers, the java.awt.Window class generally is not. For this reason, the children of the Window class are separated to ease explanation and
understanding because of the functional difference.
|
To create a new instance of a Frame,
there are two constructors you will find useful. They are of the
format as follows:
Frame AFrame = new Frame();
Frame BFrame = new Frame("This one has a title, man.");
Both constructors declare instances of the Frame
class and then allocate space for them. The difference is that
the BFrame frame is declared
to have a title from the start. You can also set the title of
the AFrame frame. If you
want to set the title of the AFrame
frame to be the String "So
do I.", use the setTitle()
method:
AFrame.setTitle("So do I.");
The setTitle method takes
an instance of the String
class to be its parameter which it then sets to be the title of
the window.
In the AWT, the sizing of windows is not done by measurement or
proportion of the screen. Instead, it is accomplished through
counting the number of pixels in a direction. To set the size
of a frame in pixels, use the resize
method of instances of the Frame
class. To set AFrame to be
100 pixels wide by 150 pixels high, you can use the following
declaration:
AFrame.resize(100, 150);
The resize method accepts
two integers: the width first, and then the height in the second
parameter position.
Caution: |
You must call the resize method on your frames. Otherwise, the default is a height of zero and a width of zero which means you get absolutely nothing when you display them unless the resize method is called with non-zero values.
|
Listing 8.1 is a small application, FrameCrazee,
that displays a frame from inside an application.
Listing 8.1. The FrameCrazee
application code.
1. import java.awt.*;
2. import java.applet.Applet;
3.
4. public class FrameCrazee extends Object {
5.
6. public static void main(String[] arg) {
7.
8. Frame AFrame = new Frame();
9. Frame BFrame = new Frame("This one has a title,
man.");
10.
11. // Set the title of the AFrame.
12. AFrame.setTitle("So do I.");
13.
14. // Resize the BFrame to width of 300 pixels,
15. // And a height of 250 pixels.
16. BFrame.resize(300, 250);
17.
18. // Display the BFrame.
19. BFrame.show();
20.
21. }
22.
23. }
Figure 8.2 is the output resulting from this application when
run using the java command-line
interpreter.
Figure 8.2: Output from the FrameCrazee application in Listing 8.1.
Caution: |
Notice that this is a Java application and not an applet. If you try to do this with an applet and expect it to work, you will be a little surprised. Instead, you have to do a little dancing to get frames incorporated with applets. This is covered a few
pages further on.
|
Lines 1 through 6 do the typical stuff you expect in a applet.
But remember, this is an application, so we can simply execute
it using the Java interpreter included in the JDK.
Lines 8 and 9 declare and initialize two instances of the Frame
class using the constructors described previously. Line 12 sets
the title for the AFrame
frame and line 16 resizes the BFrame
frame to be 300 pixels wide by 250 pixels high. And finally, line
19 displays the BFrame using
the show method of the frame
class. But where is the AFrame
declared and initialized in line 8? All you can see is the BFrame
frame displayed in the output in Figure 8.2. The show()
method of the frame isn't invoked to set it visible.
But importantly, why is this an application and not an applet
like all of the others? Isn't this a book focusing on the creation
of Java programs for the Web? Well, the problem is that instances
of the Frame class are not
allowed to be owned by a derivative of the Applet
class. Instead, you have to override the Frame
class and then use that class when defining frames in your applets.
Otherwise, you discover that frames owned by applets usually appear,
but functionality disappears. Using frames in applets is covered
after the next section on the show()
method.
Showing and Hiding Frames
The show() method of the
Frame class is the means
by which you set a frame to show itself to the world and be active.
To set a frame named CFrame
to display itself, use the following code:
CFrame.show();
If defined correctly, the CFrame
is displayed. The opposite of the show()
method is the hide()method.
It is called in the same manner as the show()
method except it causes the frame to become invisible again.
Frames and Applets
As noted before, frames cannot belong to applets directly. Instead,
you have to sidestep this a bit. The process to do so is not difficult.
It involves the following process.
In your applet, after you close your last "}",
declare another class called something like FrameJr.
Set this class to extend
the frame class. Inside of the class body, you declare that you
want to construct the FrameJr
class. Constructors are covered in Chapter 7,
"The Order Entry System: Entry Fields, Labels, and Validation."
Constructors function to set the properties and do some initial
setup when called. To set the FrameJr
class, use the following declaration:
class FrameJr extends Frame {
FrameJr (String InTitle) {
super(InTitle);
.
.
}
}
When an instance of your class FrameJr
is declared in your applet using the following statement,
Frame AFrameJr = new FrameJr(Title);
the constructor of your super
class (which is your class's parent, the one it extended) is called
and your Frame is created
just like normal. You can also include any other setup tasks you
wish to deal with inside of the constructor for your class. For
example, you might want to add an "!" to the end of
your title before constructing it. To do this, change your InTitle
string before you call the super of your class.
Caution: |
Notice that there is no constructor with which you can build an instance of FrameJr with no title. If you wish for this to work, you must declare another constructor inside of the class declaration which accepts no parameter and then calls
super() with no parameter.
|
Tip: |
This method of reconstruction of your classes is not limited to frames. It works for any class. For example, you might want to create a version of the String class whose constructor accepts a string and removes all of the capital letters. You can
write a class to extend the String class and then in the constructor remove all of the capitals before you call the super(), which is the string's original constructor.
|
Allowing User Resizing of Frames
Another important method you can use with the Frame
class is the setResizeable(boolean)
method. This method either turns on or turns off the capability
for the user to change the size of the frame being displayed.
If you send a value of false
to the method, the user is no longer permitted to change the size
of the frame. A true value
allows resizing of the window. The default setting when a frame
is initialized is true, indicating
that the user can resize the window.
Setting the Frame's Icon
One of the most interesting features of frames in the AWT is the
capability to set the icon of the frame. This is accomplished
using the setIconImage(AnImage)
method, which accepts a parameter which is of the Java type Image.
This type is covered in the next chapter, which covers Java-based
graphics. At that time, the Order Entry System logo is set to
be the icon.
Frame Menu Bars
Menu bars attached to frames are the typical pull-down menus customarily
attached to windows on almost every window-based system, including
those which are text-based along with the typical graphical-based
systems. If you've used Microsoft Windows, X Window, or MacOS,
you should be familiar with the typical format of including pull-down
menus across the top of a window border. Frame menus are implemented
using the MenuBar class.
There is one major constructor for the MenuBar
class:
MenuBar AMenuBar = new MenuBar();
You must then set your Frame to have its menu bar as the AMenuBar.
This is done using the SetMenuBar()
method of the Frame class.
To set the AMenuBar as the
menu bar of the AFrame, use
the following code line:
AFrame.setMenuBar(AMenuBar);
Each individual item along the menu bar is constructed from the
Menu class. There are two
major constructors for the Menu
class:
Menu AMenu = new Menu("One");
Menu BMenu = new Menu("Two", true);
Both constructors accept the first parameter as a string which
sets what the text label for each menu is across the top of the
frame. The second constructor adds another parameter of the Boolean
type. If the parameter is true
then the menu is removable. If it is false
then it is not. The default is false.
The following line adds the AMenu
class from above to your menu bar:
AMenuBar.add(AMenu);
This code adds an option labeled "One" to your menu
bar. You can also add menu items to your instance of the Menu
class as well as adding other menus. It is also possible to add
checkboxes to your menus. To do so, declare a checkbox as in Chapter 6,
"The Order Entry System: Adding Features and Handling Events."
Then, insert it into the menu where you wish it to belong. Also
in the same fashion as in Chapter 6, handle
the events that the checkbox generates either in the action
or handleEvent method of
your program.
To add menu items to your menus, you can declare instances of
the MenuItem class. The MenuItem
constructor accepts a string parameter which is the text label
of the item when it appears on the menu:
MenuItem AMenuItem = new MenuItem("Hey!");
You can also add text only to your menus as choices. The format
for doing this is:
Menu.add("A choice!");
If you are going to do this, be prepared to use the action
method to facilitate handling the event. If you're set on using
handleEvent, then use just
the MenuItem class.
Menus in a Nutshell
Menus aren't always easy to grasp because of the multiple classes.
To summarize, the whole menu bar starts with an instance of the
MenuBar class. This instance
is then set to be the menu bar for a frame using the setMenuBar
method of the frame.
Then, menus are added to the menu bar. (Menus are the list that
falls down when you click on a label contained in the menu bar.)
Menus can be added to other menus or to instances of the class
MenuItem. Menu items function
as text labels. Their purpose as separate variables is to give
you a target if you decide to use the handleEvent
method.
To create a menu bar, follow these steps:
- Create an instance of the MenuBar
class.
- Set your frame's MenuBar
to be the instance declared above.
- Create multiple Menus
to be in your menu bar.
- Add and create each MenuItem
and sub-menu you wish to include.
- Add all of the pieces in Step 4 to their corresponding Menu
in Step 3.
- Add your menus to the instance of MenuBar.
To visually help you grasp the organization of menu bars, Figure
8.3 is a typical menu hierarchy of insertion.
Figure 8.3 : A typical menu hierarchy of insertion
Tip: |
Remember, items added to panels, menus, and so forth are always placed in the order in which they are added. In Java, this is generally left to right or top to bottom.
|
Events and Menus
Handling events generated by menus is most easily done in the
action method of your AWT
programs. When an instance of the MenuItem
class fires a call to the action
method, the first parameter is the Event
itself. The second parameter is the string of the menu item generating
the event. This can be used for advanced tasks, if need be, such
as receiving menu items generated without declaring a MenuItem
first. Once you have experience, you can use items like the instanceof
operator to simplify your handling of events. But for the time
being, going for the simple way is a good idea.
The following if statement
block works in either event handling method:
if (evt.target == SomeMenuItem) {
// Do whatcha like . .
} else . . .
If you are using a checkbox or other component in the menu, you
can use the same format with a different target.
Setting the Frame Cursor
This is, in my opinion, one of the coolest things about the Frame
class. You have the capability of changing the appearance of the
cursor of the frame. There are a number of different cursors available.
Table 8.1 is a list of the cursor constants that you can use to
set the cursor. To find this information, look at javasrcawtFrame.java.
Table 8.1. The multiple cursor constants available
to set the cursor of frames.
Cursor Constants |
DEFAULT_CURSOR
|
CROSSHAIR_CURSOR
|
TEXT_CURSOR
|
WAIT_CURSOR
|
SW_RESIZE_CURSOR
|
SE_RESIZE_CURSOR
|
NW_RESIZE_CURSOR
|
NE_RESIZE_CURSOR
|
N_RESIZE_CURSOR
|
E_RESIZE_CURSOR
|
W_RESIZE_CURSOR
|
S_RESIZE_CURSOR
|
HAND_CURSOR
|
MOVE_CURSOR
|
To set the cursor of a frame, use the setCursor
method. To set the cursor of the frame AFrame
to the crosshair cursor, use the following code segment:
AFrame.setCursor(CROSSHAIR_CURSOR);
There is also a getCursor
method which returns an integer which is one of the above constants.
You can use this function to check which cursor is being used.
The available Frame class
methods are summarized in Table 8.2.
Table 8.2. Frame methods.
Method | Description
|
String getTitle()
| Returns a String which is the title of the window.
|
setTitle(String)
| Accepts a String parameter that is then set to be the title of the window.
|
Image getIconImage()
| Returns an instance of Image (see next chapter) that is the icon used on the window.
|
setIconImage(Image)
| Accepts an instance of Image that is then set as the icon for the window.
|
MenuBar getMenuBar()
| Returns the menu bar for the window. |
setMenuBar(MenuBar)
| Sets the menu bar for the window. |
remove(MenuComponent)
| Removes the specified menu bar from the window frame.
|
dispose()
| Gets rid of the frame and frees all of the resources it is using.
|
boolean isResizeable()
| true or false depending on whether the dialog is set to be resizeable.
|
setResizeable(boolean)
| Sets the ability for the user to resize the dialog window.
|
setCursor(integer)
| Accepts an integer which is one of the cursor constants listed previously.
|
integer getCursorType();
| Returns an integer which is one of the cursor constants listed previously.
|
Using Applets as Applications |
Web browsers incorporate a Java interpreter to interpret the Java bytecodes to be able to execute applications. The executable called "java" included in the JDK does this also. To execute a Java application, use the command line "Java
YourClassHere". To convert your applets to run as stand-alone applications, there are two major methods.
Method one is the simplest of the two. The process involves creating a public void main(String arg[]) in your applet. Then, create a new instance of the Frame class, initialize it and call the applet init() and start()
methods, and then add your applet to the frame. Then, show the Frame containing the applet. The following code demonstrates this technique inside an applet called AApplet.
public void main(String arg[]) {
// Create the new instance of the Frame class.
Frame AFrame = new ("Morrissey Fan-Club");
// Initialize the frame and the applet.
AFrame.resize(300, 300);
AApplet.init();
AApplet.start();
// Add the applet to the frame.
AFrame.add(AApplet);
// Show the frame.
AFrame.show(AApplet);
}
.
.
Method two is tough, but you should use it if you want to keep up the efficiency level. First, change the class from extending the applet class to extending the Frame class. Then, modify your applet to run with the knowledge that the
main(String arg[]) function is the only one called by the Java runtime. The init(), run(), etc. methods are no longer called because those are specific to the applet class. You, however, can set your main method to call
the init() method.
Unless you have a complete understanding, you should probably stick to method one.
|
Dialogs are another subclass of the java.awt.Window
type. They are used for simple alerts, information providing to
the user, or simple data entry. You see these every time your
windows system can't find a file or the system wants to know what
file you want. In fact, the AWT provides a predefined file dialog
for your use. Of course, in writing applets it isn't of much use
since applets can't load or save local files. But remember, applications
do have unlimited local access to the file system.
There are two key states dialogs can be in. In one state, a dialog
can demand that it receives attention enough to finish its tasks
before any other window is allowed to be active. An applet in
this state is typically called "Modal." There are multiple
other ways to refer to a window that doesn't demand attention
in this manner ranging from non-modal to modeless to unmodal.
This book refers to them as non-modal.
Dialogs are declared in the java.awt.Dialog
class. As stated before, dialogs are a subclass of the java.awt.Window
class. As such, dialogs are "siblings" with the frame
class. The two classes share the features of having a title, and
of either being resizeable or not. They share these characteristics
and you can use the same methods to set their characteristics
(setTitle(String), isResizeable(),
and so on).
The Dialog class is dependent
on the Frame class. When
you declare a dialog, you must attach it to an instance of the
Frame class. There are two
major constructors for the java.awt.Dialog
class. The following two lines construct and create two different
instances of the Dialog class,
ADialog and BDialog:
Dialog ADialog = new Dialog(AFrame, ABoolean);
Dialog BDialog = new Dialog(AFrame, TitleString, ABoolean);
Both of these declarations construct new instances of the Dialog
class. The first parameter in each is the frame to which the dialog
box belongs. The second constructor takes a string parameter which
the system sets to be the dialog box title. And the final parameter
in each is a Boolean value or variable which sets the modality
of the dialog box. A true value indicates that the dialog box
is modal (demands attention and resolution of its desires before
any other window is permitted attention) and a false value indicates
otherwise.
Dialogs share much with frames in terms of methods. As mentioned
before, both the Frame class
and the Dialog class use
the getResizeable() and setResizeable(boolean)
methods. They also share the resize(integer,
integer) method which sets the window size.
Table 8.3 summarizes the methods available in the Dialog
class.
Caution: |
Remember, for every class which is a descendant of the Window class (including Frame, Dialog, and FileDialog), you must specify the window size using the resize(integer width, integer height) method. Otherwise,
you get a window of zero width and zero height, which results in a non-existent and invisible window.
|
Table 8.3. Dialog methods.
Method | Description
|
boolean isModal
| true or false depending on whether the dialog is modal.
|
String getTitle()
| Returns a string that is the title of the dialog.
|
setTitle(String)
| Sets the dialog title to the String parameter.
|
boolean isResizeable()
| true or false depending on whether the dialog is set to be resizeable.
|
setResizeable(boolean)
| Sets the ability for the user to resize the dialog window.
|
The applet in Listing 8.2 attaches two dialogs to an instance
of the Frame class.
Listing 8.2. The DialogCrazee
applet code.
import java.awt.*;
import java.applet.Applet;
public class DialogCrazee extends Applet {
// Define and initialize your main frame window.
Frame AFrame = new FrameJr("Dialog Crazee");
// Define an untitled modal dialog.
Dialog ADialog = new Dialog(AFrame, true);
// Define a titled, non-modal dialog.
Dialog BDialog = new Dialog(AFrame, "I've gotta title!",
false);
public void init () {
// Resize the AFrame to width of 100 pixels,
// And a height of 150 pixels.
AFrame.resize(100, 150);
// Resize each of the dialogs so you can see them.
ADialog.resize(100,100);
BDialog.resize(200,200);
// Add a label to each of the dialogs.
ADialog.add(new Label("I am ADialog."));
BDialog.add(new Label("I am BDialog."));
// Display the AFrame.
AFrame.show();
}
}
class FrameJr extends Frame {
FrameJr (String InTitle) {
super(InTitle);
}
}
What occurs in this applet is relatively simple. The initial coding
declares the different variables. Then, they are set up in the
init() method. And finally,
the AFrame is told to appear.
But if you execute this applet, you are in for a surprise. Where
are the dialogs you have worked to create? Well, they haven't
been told to show themselves.
Since dialogs are usually set to appear when some event happens,
such as the user wishing to load a file, that prompts the program
to display it. This fits in great with the idea of handling events
in the AWT. You connect the appearance of each one of the dialogs
with an action that takes place in the frame.
To generate these actions in the original AFrame,
you create two buttons in the original frame labeled "A"
and "B", then set the handleEvent
method to display the respective dialog when the user presses
the buttons.
The first step is to add a couple of new buttons to the AFrame
frame. To do this, use the constructor in Chapter 6:
new AButton = new Button("A");
new BButton = new Button("B");
Then, insert these buttons into the AFrame
using the add method. The
handleEvent method in the
previous example also needs to be created. Insert two if
blocks to check and see if one of the buttons is the originator
of the event.
The improved DialogCrazee
applet follows as Listing 8.3. The output from the DialogCrazee
applet appears in Figure 8.4.
Figure 8.4 : The output from the DialogCrazee applet.
Listing 8.3. The improved DialogCrazee
applet code.
import java.awt.*;
import java.applet.Applet;
public class DialogCrazee extends Applet {
// Define and initialize our main frame
window.
Frame AFrame = new FrameJr("Dialog
Crazee");
// Define an untitled modal dialog.
Dialog ADialog = new Dialog(AFrame, true);
// Define a titled, non-modal dialog.
Dialog BDialog = new Dialog(AFrame, "I've
gotta title!", false);
// Define the two new buttons to go into
the frame.
Button AButton = new Button("A");
Button BButton = new Button("B");
public void init () {
//
Resize the AFrame to width of 100 pixels,
//
And a height of 150 pixels.
AFrame.resize(100,
150);
//
Resize each of the dialogs so you can see them.
ADialog.resize(100,100);
BDialog.resize(200,200);
//
Add a label to each of the dialogs.
ADialog.add(new
Label("I am ADialog."));
BDialog.add(new
Label("I am BDialog."));
//
Add the two buttons to the frame.
add(AButton);
add(BButton);
//
Display the AFrame.
AFrame.show();
}
public boolean handleEvent(Event InEvent) {
if
(InEvent.target == AButton) {
ADialog.show();
}
else
if
(InEvent.target == BButton) {
BDialog.show();
}
return
super.handleEvent(InEvent);
}
}
class FrameJr extends Frame {
FrameJr (String InTitle) {
super(InTitle);
}
}
Note: |
Ideally, you want the dialogs which belong to a frame to be declared inside of that frame. Then, when you handle an event, you call a public method of the FrameJr (or whatever you call it) class which then shows the dialog. However, this seems
simpler. It is not difficult to place your dialogs inside your frame constructor so plan on doing that. Even though the code is a little choppier, it is sound coding practice.
|
Caution: |
If you run this applet and then try to close the frame window, you notice that nothing happens. To make the close button functional, you need to add a handleEvent() method to the declaration of an instance of the Frame class since it
doesn't include functionality for this feature as a default. If you are creating an application which is an extension of the Frame class, place the handleEvent() method in the class declaration itself. If you are using the method
described here to place frames into applets, place the handleEvent() method inside of that class declaration.
To accomplish this inside of your secondary class (for example, one such as the FrameJr class), include the following if block inside of a handleEvent() method for your frames:
if (InEvent.id == Event.WINDOW_DESTROY)
{
dispose();
}
.
|
A special dialog subclass is dedicated to saving, loading, and
dealing with files. Each implementation of the AWT for each different
windowing system mimics that system's standard native file dialog.
If you implement the FileDialog
class in X Window for example, you get the typical X Window file
dialog.
There are two major constructors for the FileDialog
class:
FileDialog AFileDialog = new (AFrame,
AString);
FileDialog BFileDialog = new (AFrame, AString, AInteger);
For both of the constructors, the first two parameters are the
same. Just as with the general dialog class, you must specify
a frame to which the dialog belongs. You also need to specify
the title for the dialog. The second constructor takes a parameter
which is one of either FileDialog.LOAD
or FileDialog.SAVE. This
constant determines whether the dialog is a load file dialog or
a save file dialog.
If the first constructor is called, an open file dialog is created.
So, in summary, to open a file, use the first constructor. To
save a file or load a file, use the second constructor with the
different constants available. There is no constant called
FileDialog.OPEN; you must
use the first constructor.
The FileDialog() class uses
many of the same methods common to descendants of the AWT Window
class, and some others. Here is a summary of the file dialog methods
in Table 8.4.
Table 8.4. Some available file dialog methods.
Method | Description
|
int getmode()
| Returns an integer constant that is one of the different constants signifying load, open, and so forth.
|
String getDirectory()
| Returns a string that is the directory of the file dialog's focus.
|
void setDirectory
| Sets the current directory focus to the String directory.
|
void setFile(StringTheFile)
| Sets the current file for the dialog. |
String getFile()
| Returns a string that is the file name of the current file in focus.
|
FilenameFilter getFilenameFilter()
| Returns the current filter of the file listing.
|
SetFilenameFilter
| Sets the current file name filter. |
Window-to-Window Data Exchange, or Connecting the Object-Oriented Way
|
In some cases, you run into problems in terms of connecting the two different classes together. For example, you want to send some data that you get in one window to another window. Or your dialog box asks for information and you wish to allow your frame
to use it.
A similar dilemma arises when dealing with other classes. You have to "hardwire" the connection between the two classes. This is contrary to one of the primary goals of object-oriented programming which is the re-usability of code. Making one
frame class so that it can only send data back to an instance of the Applet class means that you need to rewrite and recompile the sender each time you want to use it with a different class. And also, you have to have a different copy of each
version of your class around for every other class it connects with.
The solution to this problem is the idea of interfaces. Interfaces are classes which have not had any method implemented. In other words, instances of interfaces are, except for local constants, a big empty. However, they allow the user to create linkages
between classes without having to worry about the different implementations. To use an interface in your applet, you must declare an instance of it. For example, if you want an interface which allows you to relate a value of an integer to another class
that uses the interface, declare the following interface:
interface MyInterface {
abstract public int AnInteger;
}
You can also declare methods inside of your interfaces by using the same abstract public format. Though the abstract isn't needed for methods since it is the only state that methods in an interface are allowed to be. In essence, you are
declaring variables and methods with concern for what they do, but saving the "how" for another class to take care of. To create a class which takes care of the implementation of your interface, you use the following class declaration:
class AFrame extends Frame implements MyInterface {
.
.
.
}
The method described first in this section "hardwires" the connection between the two classes. You can also do the following when you want to use information contained in the class which implements the interface:
((MyInterface) getParent()).AnInteger
You can also do the same with methods by being able to call the methods which were declared in the interface and then implemented in the other class:
((MyInterface) getParent()).AVoid();
What is happening in each of these statements is that the result of the function getParent() (which returns the immediate parent of an object) is cast to be an instance of the interface type. Then, the method or variable of the interface, which is
implemented by the other class, is accessed.
Well, can't you avoid all of this trouble and hardwire it in? Yes, but there are two reasons you don't want to. For one, Java compilers aren't very fast at the moment. A five hundred line program can take a minute to compile. If you have to rewrite one
line of one five hundred line class to get it to connect with another class and then compile it for five different connections, it is going to take time.
Finally, the reason this is included in this section is that it is very useful in terms of the AWT and its windowing capabilities. You want to write your dialogs to be able to be reused with different frames you create.
|
It is time to apply some of the new concepts covered in this chapter
to the Order Entry System. The first topic to cover is the code
changes necessary to make the Order Entry System function as a
stand-alone window. This includes inserting a button in the applet
panel which the user can press to call up the order window. Also,
some pop-up dialogs are incorporated into the applet. You want
a dialog to appear specifically when the user leaves the name
field empty. It is also simple to incorporate other dialogs to
appear in response to other events.
Using the concepts covered earlier in this chapter, this section
covers the method to convert the Order Entry System to a stand-alone
window. You add a button to the applet panel which the user can
press to bring up the window. Then, the user can fill in the form
on the window.
To have a frame belong to an applet, you first have to declare
another class inside of the applet file which extends the Frame
class. This is because frames cannot belong directly to applets.
Instead, sidestep this by declaring your own class which overrides
the Frame class. The name
for the new class type is called the OrderEntryFrameType.
The declaration for this class type is as follows:
class OrderEntryFrameType extends Frame
{
FrameJr (String InTitle) {
super(InTitle);
}
.
.
.
}
But instead of adding the components and setting up variables
as in the original Order Entry System in the applet's init()
method, you need to create a method in the OrderEntryFrame which
accomplishes all of the component insertion and setup done in
the applet's init() method.
To do this, you copy the corresponding code in the init()
method to a method you create in the OrderEntryFrameType.
Call this method setup().
So, the format for the OrderEntryFrameType
class declaration is as follows:
class OrderEntryFrameType extends Frame
{
FrameJr (String InTitle) {
super(InTitle);
}
public void setup() {
// The init() code body goes here. . .
.
.
}
}
The components that were once added to the applet panel in the
applet's init() method are
now added to the frame itself. Also all of the variables that
are used in the Order Entry System are placed into the frame itself.
The full code cost listing of this is included in the complete
listing of the applet coming up.
Since these variables are moved into another class, shut them
off from being accessed by parent classes. Follow this practice
of data encapsulation. All accesses to the data contained in the
OrderEntryFrameType are done
through methods and functions declared in the class itself.
Almost all of the methods of the original applet are moved to
the frame class itself. The function of the system is encapsulated.
This makes it easy to actually run the system as an application
if need be.
The newly changed Order Entry System follows as Listing 8.4. Here
are the major improvements as of this iteration:
- The majority of the function is now transferred to a separate
frame. This frame is declared in a separate class in the applet
file. All of the functions and variables which had been in the
applet are moved to the frame itself. Notice that the applet code
is translated to an instance of the Frame
class which belongs to the applet class. The action
and handleEvent methods are
also transferred. The new frame instance is completely independent
of the applet. (In fact, two instances of the OrderEntryFrameType
can just as easily be declared and both of them implemented.)
- Also, a button is added to the applet face. The user's activation
of this button results in the initialization and display of the
frame and also deactivates the button so that another order entry
frame cannot be activated.
Listing 8.4. Another iteration of the Order Entry System.
import java.awt.*;
import java.applet.*;
public class OrderEntrySystem extends Applet {
// Declare an instance of your frame class defined later
in the // file.
OrderEntryFrameType
OESFrame;
// Declare and initialize
the button which will be on the applet
// face and the user can click to activate the order frame.
Button Order = new
Button("Click to Order");
public void init()
{
add(Order);
}
public boolean handleEvent(Event
InEvent) {
if (InEvent.target == Order) {
// Disable the order button.
Order.disable();
//
Construct the OESFrame.
OESFrame = new OrderEntryFrameType("Order
Entry System");
OESFrame.resize(340,400);
// The setup method which initializes
the frame face and
//
the components in it.
OESFrame.setup();
// Display the order frame.
OESFrame.show();
}
// Let the parent handle the event.
return super.handleEvent(InEvent);
}
}
/* This class declares the new extension of the frame class which
will allow you to utilize a frame in the applet. */
class OrderEntryFrameType extends Frame {
// This is the constructor for your new class.
OrderEntryFrameType
(String InTitle) {
// Call the Frame
constructor.
super(InTitle);
// Set the layout of the frame (this has to be done
to make things work).
// This concept
will be covered later on in this chapter.
setLayout(new FlowLayout());
}
// This method does
the construction of the frame panel.
public void setup() {
// Add and create three buttons.
SubmitButton
= new Button("Submit");
add(SubmitButton);
ClearButton
= new Button("Clear");
add(ClearButton);
QuitButton = new Button("Quit");
add(QuitButton);
// Add and create the repeat customer
checkbox.
Checkbox RepeatCustCheckBox = new Checkbox("Repeat Customer?");
add(RepeatCustCheckBox);
// Add a label to the ContactMethodGroup.
add(new
Label("How would you like to be contacted? "));
//
Declare the CheckboxGroup, and allocate space.
CheckboxGroup ContactMethodGroup;
ContactMethodGroup
= new CheckboxGroup();
//
Create some checkboxes to put in the group.
Checkbox EmailBox = new Checkbox("Email",ContactMethodGroup,true);
Checkbox
PhoneBox = new
Checkbox("Phone",ContactMethodGroup,false);
Checkbox
MailBox = new
Checkbox("US Mail",ContactMethodGroup,false);
// Add the checkboxes into the applet
panel.
add(EmailBox);
add(PhoneBox);
add(MailBox);
//
Label the item list.
add(new Label("Products"));
// Create the list, 4 items visible, no
multiple
//
selections.
ProductList = new List(4, false);
// Add items to the List.
ProductList.addItem("Oscar");
ProductList.addItem("Lionhead");
ProductList.addItem("Jack
Dempsey");
ProductList.addItem("Angelfish");
// Add the List to the Applet panel.
add(ProductList);
//
Add a label to the choice of sizes.
add(new Label("Size:"));
// Create the Choice box.
SizeChoice
= new Choice();
//
Add items to the List.
SizeChoice.addItem("Jumbo");
SizeChoice.addItem("Large");
SizeChoice.addItem("Medium");
SizeChoice.addItem("Small");
//
Add the Choice to the Applet panel.
add(SizeChoice);
// Add a label to the slider.
add(new
Label("Amount:"));
//
Create a vertical slider, initial value of 0,
// minimum value of 0, maximum value of
144.
OrderAmountSlider
= new Scrollbar(Scrollbar.HORIZONTAL, 0, 0, 0, 144);
// Insert the slider to the Applet panel.
add(OrderAmountSlider);
//
Insert the label which says how many are set to be ordered
//
of the item.
add(AmountLabel);
//
Add the subtotal label and a label saying that it is
//
the subtotal.
add(new
Label("Subtotal: "));
add(SubTotalLabel);
//
Add the total label and a label saying that it is the total.
add(new
Label("Total: "));
add(TotalLabel);
// Insert
a label to signify that this is the personal information
// (address, etc.) section and also insert text fields to prompt
// for
that information.
add(new Label("Your information:
"));
add(new Label("Name:"));
add(NameEntryField);
add(new
Label("Street:"));
add(StreetEntryField);
add(new
Label("City:"));
add(CityEntryField);
add(new
Label("Zip:"));
add(ZipEntryField);
// Add a label to the comment text area.
add(new
Label("Comments:"));
// Add
the comment box.
add(CommentTextArea);
// Method which resets all of the internal values.
resetValues();
}
// The subtotal and total variables.
private double SubTotalOne
= 0.0;
private double Total = 0.0;
// The price multipliers for each different product size.
private double multiplierSmall
= 0.5;
private double multiplierMedium = 1.0;
private double multiplierLarge
= 1.5;
private double multiplierJumbo = 2.25;
// The local constant base prices.
static double ProdOneBaseValue
= 1.0;
static double ProdTwoBaseValue = 1.33;
static double ProdThreeBaseValue
= 1.75;
static double ProdFourBaseValue = 8.75;
// Declare all of the variables you'll use.
private Button SubmitButton;
private Button ClearButton;
private Button QuitButton;
private Checkbox RepeatCustCheckBox;
private Checkbox MailBox;
private Checkbox EmailBox;
private Checkbox PhoneBox;
private List ProductList;
private Choice SizeChoice;
private Scrollbar OrderAmountSlider;
// The labels which will be variable and change when
// the other selections
are changed.
private Label SubTotalLabel = new Label("$0.0 ");
private Label TotalLabel
= new Label("$0.0 ");
private Label AmountLabel = new Label("$0.0 ");
private Label PricePerItemLabel
= new Label("$0.0 ");
// The entry field
for the user to enter a name.
private TextField NameEntryField = new TextField(25);
private TextField ZipEntryField
= new TextField(5);
private TextField StreetEntryField = new TextField(25);
private TextField CityEntryField
= new TextField(25);
// The comment entry area.
private TextArea CommentTextArea
= new TextArea(4, 25);
private void updateValues()
{
int
WhichChoice = SizeChoice.getSelectedIndex();
int AmountSelected
= OrderAmountSlider.getValue();
int
WhichProduct = ProductList.getSelectedIndex();
double CurrentBasePrice
= 0.0;
double
CurrentModifier = 0.0;
switch (WhichProduct)
{
case
0:
CurrentBasePrice
= ProdOneBaseValue;
break;
case
1:
CurrentBasePrice
= ProdTwoBaseValue;
break;
case
2:
CurrentBasePrice
= ProdThreeBaseValue;
break;
case
3:
CurrentBasePrice
= ProdFourBaseValue;
break;
}
switch (WhichChoice)
{
case
3:
CurrentModifier
= multiplierSmall;
break;
case
2:
CurrentModifier
= multiplierMedium;
break;
case
1:
CurrentModifier
= multiplierLarge;
break;
case
0:
CurrentModifier
= multiplierJumbo;
break;
}
AmountLabel.setText(Integer.toString(AmountSelected)+
" ");
double PricePerItem
= (CurrentBasePrice*CurrentModifier);
PricePerItemLabel.setText(Double.toString(PricePerItem)+
" ");
double SubTotal
= (CurrentBasePrice*CurrentModifier*AmountSelected);
SubTotalLabel.setText(Double.toString(SubTotal)+
" ");
TotalLabel.setText(SubTotalLabel.getText());
}
// This method will
be called when the user presses the "Clear" button and
// also when the applet is initialized in the init() method.
public void resetValues()
{
// Reset all
of these labels to zero.
SubTotalLabel.setText("$0.0 ");
TotalLabel.setText("$0.0
");
AmountLabel.setText("0 ");
PricePerItemLabel.setText("$0.0
");
// Clear all
of the lists and choices.
ProductList.select(0);
SizeChoice.select(0);
OrderAmountSlider.setValue(0);
// Clear all of the text fields.
NameEntryField.setText("");
StreetEntryField.setText("");
CityEntryField.setText("");
ZipEntryField.setText("");
}
public boolean handleEvent(Event
InEvent) {
if (InEvent.id == Event.SCROLL_LINE_UP ||
InEvent.id
== Event.SCROLL_LINE_DOWN) {
updateValues();
} else
if (InEvent.target == ProductList) {
updateValues();
} else
if (InEvent.target
== ClearButton) {
resetValues();
} else
if (InEvent.target == QuitButton) {
// Quit the applet.
System.exit(0);
} else
if (InEvent.target == SubmitButton) {
// Submit
the order.
}
return super.handleEvent(InEvent);
}
public boolean action (Event InEvent, Object SomeObject)
{
if (InEvent.target
== SizeChoice) {
updateValues();
return true;
}
else
if (InEvent.target == NameEntryField) {
// Is the
field empty? If so, we will later add a pop-up dialog
// box to alert the users that they have not
entered their name.
return
true;
} else
return false;
}
}
The Order Entry System is still growing. Next, the ability to
display a dialog box in response to a user action is added. Notice
that the framework for this ability is built in the action
method of the OrderEntryFrameType
class that has been created.
Figure 8.5 is the Order Entry System when viewed from the Appletviewer
utility.
Figure 8.5 : The Order Entry System from the Appletviewer utility.
The disable() and enable() Methods
|
These two methods allow you, the programmer, to deactivate and activate your components. It is used in the latest version of the Order Entry System to disable the button which calls the Order Entry System window. You can use these methods to enable and
disable your components when you wish.
|
Adding a pop-up dialog to the Order Entry System is simpler than
converting to a stand-alone window. The framework for displaying
the dialog window is already completed. Now, create a new class
which extends the Dialog
class as you create a new class to create the OrderEntryFrameType.
Then, declare an instance of your new dialog box type and implement
it in the frame type.
When the name text field creates an event, it is handled by the
action method. The action
method is set to recognize this event, except it is not set to
do anything when it gets the event. You are going to change this.
The first step is to declare an extension of the Dialog
class.
class WarningDialog extends Dialog {
private Button OkButton
= new Button("OK");
private Label ALabel;
WarningDialog(Frame HostFrame, String Message) {
super(HostFrame,
"Warning!", false);
ALabel = new
Label(Message);
resize(180,100);
setLayout(new FlowLayout());
add(ALabel);
add(OkButton);
}
public boolean action
(Event InEvent, Object Param) {
if (InEvent.target == OkButton) {
hide();
}
return true;
}
}
Add this class declaration to the Order Entry System class declaration
file. Then, declare an instance of it inside of the OrderEntryFrameType:
WarningDialog WDialog = new WarningDialog(this,
"You have not entered a name. ");
To display the warning dialog, call the show()
method, which is inherited from the dialog class when the dialog
class is extended:
WDialog.show();
Figure 8.6 shows what happens when the user of the Order Entry
System leaves the name field blank.
Figure 8.6 : The Order Entry System with the WarningDialog class included.
The new extension of the Dialog
works great, but look at what happens when the dialog box window
is resized in Figure 8.7.
Figure 8.7 : The WarningDialog box resized.
The layout of the components in the dialog box is at fault. For
now, the default layout (which is the FlowLayout
manager) has been used. But it is obvious that this isn't going
to work. The next section covers the different AWT layout managers
and applies one to the Order Entry System.
Tip: |
The this keyword is very useful in Java. It refers to the current class. For example, you want to attach a dialog to a frame and declare that dialog in the frame. You say,
Dialog D = new Dialog(this, "Sample", true);
|
AWT layout managers are the means by which you, the programmer,
can give a set of general rules to determine how your components
in a container are arranged. Remember, applets are standard with
an initial panel incorporated so you can set the layout of your
applet face.
In other windowing systems such as Microsoft Windows, the programmer
specifies actual coordinates for different components of the window
to be arranged. However, this is impossible in Java since the
goal is platform independence. The window you create under Solaris
should work on a Macintosh, a DEC Alpha, and an NeXT. This goal
of independence makes some tasks more difficult. As for the layout
of components in general, it is one of the tougher concepts in
Java. It is much easier to set the exact coordinates like other
systems. While container layout is difficult, it has been designed
to be powerful and relatively convenient to implement.
In any case, the following sections outline the five Java AWT
layout managers.
The FlowLayout manager is
the default layout manager for applets. If you look back, you
notice that the applets constructed earlier follow a general layout
pattern. Components are inserted left to right until the end of
a row is reached. Then, the same process begins on the next line
until that row is filled also. If an attempt is made to place
too many components in a panel, the ones that didn't fit are left
out.
To set the layout manager you wish to use, the setLayout()
method is available. The following code line sets the layout in
a panel APanel to the FlowLayout
manager:
APanel.setLayout(new FlowLayout());
There are multiple options you can use with the FlowLayout
manager. First, the manager allows you to specify the alignment
of the layout. There are three constants available in the FlowLayout
class: FlowLayout.LEFT, FlowLayout.CENTER
(the default), and FlowLayout.RIGHT.
You can also set the vertical and horizontal "padding"
between different components. This is done in one version of the
FlowLayout constructors.
The default value for this padding is 5 pixels vertical and 5
pixels horizontal.
Table 8.5 summarizes the FlowLayout
constructors.
Table 8.5. The constructors for the FlowLayout class.
Constructor | Effect
|
FlowLayout()
| Default constructor. |
FlowLayout(align)
| align is one of FlowLayout.LEFT, FlowLayout.CENTER, or FlowLayout.RIGHT.
|
FlowLayout(align, HPad, VPad)
| HPad and VPad are integers specifying the horizontal and vertical padding between components in terms of pixels.
|
The following r code declares a panel, sets the internal panel
layout, and adds a component to that panel:
Panel P = new Panel();
P.setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 15);
P.add(new Label("Text.");
The BorderLayout manager
divides a container into five different segments. These are "North,"
"South," "Center," "West," and "East."
Of course, the "North" segment of a container is the
top, the "West" is the left and so on. There are two
major constructors for the BorderLayout
manager:
BorderLayout BLayout = new BorderLayout();
BorderLayout BLayout2 = new BorderLayout(10, 15);
The second constructor sets the horizontal and vertical padding
just like in the FlowLayout
manager. To add components to a container using this manager,
you must specify the region which the component occupies like
this:
add("West", AComponent);
This inserts the AComponent
into the western (left) region of the container.
The following applet declares an instance of the BorderLayout
class and then adds one button to each of the five areas. The
code is in Listing 8.5.
Listing 8.5. The BorderExample applet code.
import java.awt.*;
import java.applet.*;
public class BorderExample extends Applet {
public void init() {
BorderLayout BLayout = new BorderLayout(5, 5);
setLayout(BLayout);
add("West", new Button("west"));
add("East", new Button("east"));
add("North", new Button("north"));
add("South", new Button("south"));
add("Center", new Button("center"));
}
}
The output from this applet is Figure 8.8.
Figure 8.8 : The BorderExample applet when viewed from the Appletviewer utility.
Notice that the different buttons expand to fill the area they
are given under this layout manager.
The CardLayout manager is
unique among the different layout managers in the AWT. Instead
of placing all of the components next to each other, it allows
components to be positioned behind each other. Basically, the
idea is that you can define a couple of component groups and then
when certain actions occur, you can switch between those groups
on the same display area.
To put the CardLayout manager
into use, first define an instance of the CardLayout
manager in your applet. Then, setLayout
of your applet to the instance you just declared. For each separate
card you want to have, create a Panel
and place in it what you want. Finally, add each of the new panels
using the add method.
Table 8.6 shows the methods available for use in the CardLayout
manager.
Table 8.6. The available CardLayout manager methods.
Methods | Effect
|
first(AContainer)
| Display the first card inserted. The parameter is the name of the parent container which implements the CardLayout manager.
|
last(AContainer)
| Same as first except showing the last item in the layout.
|
next(AContainer)
| Display the next card inserted. The parameter is the name of the parent container which implements the CardLayout manager.
|
show(Acontainer, AString)
| Display the card. |
Overall, this manager isn't as functional as it can be. Ideally,
the tabbed card layouts found in systems such as Windows 95 can
be implemented. However, this isn't possible with the current
AWT. Hopefully, the carding features of the AWT will be a feature
which is extended in future development of Java.
GridLayout
The GridLayout manager divides
a container into uniformly sized rows and columns. Imagine drawing
a grid over a container and then each component filling a grid
square as you add() them
to the container. The placement continues from left to right and
top down. There are two major constructors for the GridLayout
manager class:
GridLayout GL1 = new GridLayout(IntRows,
IntColumns);
GridLayout GL2 = new GridLayout(IntRows, IntColumns, HPad, VPad);
In the first constructor, the two parameters specify the number
of grid rows and columns to divide the container into. The second
constructor also accepts the number of pixels of horizontal and
vertical padding between the grid squares. This manager isn't
great for larger layouts, but useful when applied to smaller containers
involved in subdividing a large display.
Note: |
The "grid" discussed in this section is not represented on the container as any lines or borders. Rather, it is a means to mentally picture the dividing of the container into uniform squares.
|
The GridBagLayout manager
extends the basic idea behind the grid layout manager. The main
difference lies in that the components can be different sizes
in terms of occupying multiple grid spaces. Where components can
only occupy one grid space in the container, there are also a
number of parameters to align the components inside of the grid.
You are also capable of setting component padding and the anchoring
of the components inside of the grid square. This is all great
and powerful, but unlike many of the other features of Java, not
very intuitive.
To implement the grid bag layout, you need to declare an instance
of the GridBagLayout class.
Then, set the layout of the container to this variable where GBL
is the local instance of the GridBagLayout
class:
GridBagLayout GBL = new GridBagLayout();
setLayout(GBL);
The multiple parameters, such as anchoring, alignment, grid position,
and so forth are declared in a class called GridBagConstraints.
To complete any of these settings for a component, you first declare
an instance of the GridBagConstraints
class. Then, you change the constants representing these parameters
in the instance of the constraints class. For example, if you
want to set the anchoring of the component inside the grid space,
you say:
Constraints.anchor = GridBagConstraints.NORTH;
where Constraints is an instance
of the GridBagConstraints
class. To associate these constraints with the component when
you add it to your container, you use the following code:
GBL.setConstraints(AComponent, Constraints);
add(AComponent);
And you continue this process for each component you want to add
using this layout manager.
Setting the Layout Constraints
As stated previously, for each component you wish to insert, you
must set the current constraints under which that component is
inserted. This has been demonstrated before when the setConstraints
method is used to set the constraints for a component which is
then inserted.
There are a large number of settings for you to set in the instance
of the GridBagConstraints
class. The primary fields of the constraints class are the gridx
and the gridy fields. These
specify the x and y coordinates of the grid space in which you
wish for your component to appear. Note that the grid squares
begin at 0,0 (the upper-left corner of your grid).
There are two ways to insert components into the grid. One way
is to specify the actual coordinates in which you want your component
to appear. The second way, and the way intended by Java's designers,
is to specify both of these constants to be the value of GridBagConstraints.RELATIVE.
The idea is that you begin placing components into the grid and
they are placed left to right, in adjacent squares. Finally, when
you want to move down to the next line, you specify the gridx.
Use the second method. Placing components in this manner means
that you also need to say when you want to go to the next row
to place the next component. To do this, set another of the constraints
to a different constant. These settings are the gridwidth
and gridheight settings in
your instance of the GridBagConstraints
class.
gridwidth and gridheight
set the amount of grid cells that a component occupies when it
gets placed. For example, a gridheight
of 2 means that the component occupies two grid cells in terms
of height. And if you want the component to occupy three cells
in width, set the gridwidth
to 3. Your instance of the constraints in the Order Entry System
is called Constraints. To
set the component to occupy three grid cells in width, use the
following line:
Constraints.gridwidth = 3;
The default for these values is 1. Leave them alone until you
are ready to begin placing components on a new row. To do this,
set the gridwidth to equal
GridBagConstraints.REMAINDER.
This signals the layout manager that this component is the last
on this row.
That takes care of the general placing of the components in the
grid. There are also a number of other constraints which allow
you to place the components inside of the grid space they are
occupying.
The first of these is the anchor
value of the GridBagConstraints.
This tells the layout manager where the component is positioned
inside of the grid box it is occupying. The acceptable values
are GridBagConstraints.SOUTH,
GridBagConstraints.NORTHEAST,
GridBagConstraints.WEST,
and so forth. All of the eight directions are covered.
The fill parameter tells
the layout manager how components such as buttons fill the grid
box that they are in. There are four possible settings. These
are demonstrated in Table 8.7.
Table 8.7. The four GridBagConstraints settings.
Setting | Effect
|
GridBagConstraints.NONE
| No expansion. |
GridBagConstraints.HORIZONTAL
| Expand to fill horizontally. |
GridBagConstraints.VERTICAL
| Expand to fill vertically. |
GridBagConstraints.BOTH
| Expand to fill both vertically and horizontally.
|
The weightx and weighty
settings determine the sizes of the different components relative
to each other. This is used to have your components spread out
to fill the container. Otherwise your components all cluster in
the center of the container. The weights are all relative to each
other. A component with a weightx
of 3 has a size three times that of a component having a weightx
of 1.
If you want to add some pixels around a component to separate
it from the other components surrounding it, use the ipadx
and ipady settings in the
constraints variable. Whatever number you set each of these values
to is the number of pixels that the layout manger places as an
empty area around your component.
Recipe for Implementing the GridBagLayout
Manager
The following steps outline the steps in implementing the GridBagLayout
manager for a container:
- Declare an instance of the GridBagLayout
manager and an instance of GridBagConstraints
in your program.
- Set the layout of your container to be the instance of the
GridBagLayout manager you
defined in Step 1.
- For each component you wish to add, either declare a new instance
of the constraints or modify an old one.
- For the constraints made available in Step 3, set the values
in that instance. For example, set gridwidth
equal to GridBagConstraints.REMAINDER
if you want to say that you are finished filling this row. Also
set other constraints such as the weightx
or fill.
- setConstraints for the
layout manager using the component name as the first parameter
and the second parameter as the constraints.
- add the component to
the container, sending the first parameter as the constraints
from Step 4 and the second as the name of the component.
- Repeat Steps 3 through 6 until you are finished.
Now you take what there is so far in the Order Entry System and
organize its appearance. The plan is to "divide and conquer"
the regions of the entry interface that you have already begun
constructing. The entire window face is designed with this goal
in mind. The primary layout (the layout manager which is used
on the window panel itself) is going to be the GridBagLayout
manager. As shown, it is by far the most powerful in terms of
getting components where you want them. There are a number of
sub-panels in use. Each subdivides the main frame window, whose
layout is managed by the PrimaryLayout
which is an instance of the GridBagLayout
class. Each individual sub-panel is named by function, such as
InfoPanel which is the sub-panel
that gets the user information. Each sub-panel which uses the
GridBagLayout manager also
has an instance of the GridBagConstraints
class to help manage it. A complete inspection of the code isn't
really necessary. The most important concept to understand is
the process of subdividing the containers to get the layout that
you want. While it is tedious (as you can tell from the length
of the code), it is the solution to provide both pretty layouts
and platform independence. Figure 8.9 is what you end up
with after it is all over.
Figure 8.9 : What the Order Entry System looks like after it is completed with this section.
Listing 8.6 is the revised setup()
and constructor implementation. It now implements the different
AWT layout managers to control the placement of the components
in the container.
Listing 8.6. The OrderEntryFrameType class code.
class OrderEntryFrameType extends Frame
{
OrderEntryFrameType
(String InTitle) {
super(InTitle);
}
WarningDialog WDialog = new WarningDialog
(this, "You have not entered a name. ");
public void setup() {
// Set the initial grid bag
layout for the frame.
GridBagLayout PrimaryLayout = new GridBagLayout();
setLayout(PrimaryLayout);
// Set the constraints for the Product
Panel, which will contain product
// choices, sizes, etc.
GridBagConstraints ProductPanelConstraints
= new GridBagConstraints();
// The Product Panel will take up the
rest of the space on this line.
ProductPanelConstraints.gridwidth = GridBagConstraints.REMAINDER;
// Declare and initialize the Product Panel.
Panel ProductPanel = new Panel();
// Set the layout for the Product Panel
and set the constraints for
// the components inside of the Product Panel.
GridBagLayout ProductPanelLayout = new
GridBagLayout();
GridBagConstraints InProductPanelConstraints =
new GridBagConstraints();
ProductPanel.setLayout(ProductPanelLayout);
// Here we will set the list panel, which will hold the
// list choice method and insertion.
Panel ListPanel = new Panel();
ListPanel.setLayout(new BorderLayout());
Label ProductLabel = new Label("Products");
ListPanel.add("North", ProductLabel);
// Create the list, 4 items visible, no multiple
// selections.
ProductList = new List(4, false);
//
Add items to the List.
ProductList.addItem("Oscar");
ProductList.addItem("Lionhead");
ProductList.addItem("Jack
Dempsey");
ProductList.addItem("Angelfish");
//
Add the List to the list panel.
ListPanel.add("Center",ProductList);
//
Add the embedded panel to the Product Panel.
InProductPanelConstraints.anchor
= GridBagConstraints.NORTH;
ProductPanelLayout.setConstraints(
ListPanel,
InProductPanelConstraints);
ProductPanel.add(ListPanel);
//
Another panel which will be embedded in the Product Panel.
Panel
SizePanel = new Panel();
SizePanel.setLayout(new
BorderLayout());
//
Add a label to the choice of sizes.
SizePanel.add("North",
new Label("Size:"));
//
Create the Choice box.
SizeChoice
= new Choice();
//
Add items to the List.
SizeChoice.addItem("Jumbo");
SizeChoice.addItem("Large");
SizeChoice.addItem("Medium");
SizeChoice.addItem("Small");
//
Add the Choice to the Applet panel.
SizePanel.add("Center",SizeChoice);
//
Add the embedded panel to the Product Panel.
ProductPanelLayout.setConstraints(SizePanel,
InProductPanelConstraints);
ProductPanel.add(SizePanel);
//
Another panel which will be embedded in the Product Panel.
Panel
AmountPanel = new Panel();
AmountPanel.setLayout(new
BorderLayout());
//
Add a label to the slider.
AmountPanel.add("North",
new Label("Amount:"));
//
Another embedded panel which will contain the slider and
//
the output label.
Panel
SliderPanel = new Panel();
SliderPanel.setLayout(new
FlowLayout());
//
Insert the label which says how many are set
//
to be ordered of the item.
SliderPanel.add(AmountLabel);
//
Create a vertical slider, initial value of 0,
//
minimum value of 0, maximum value of 144.
OrderAmountSlider
= new
Scrollbar(Scrollbar.HORIZONTAL,
0, 0, 0, 144);
//
Insert the slider to the Applet panel.
SliderPanel.add(OrderAmountSlider);
AmountPanel.add("Center",
SliderPanel);
// Add the embedded panel to the Product
Panel.
ProductPanelLayout.setConstraints(AmountPanel,
InProductPanelConstraints);
ProductPanel.add(AmountPanel);
//
The last panel which will be embedded in the Product Panel.
Panel
TotalPanel = new Panel();
TotalPanel.setLayout(new
BorderLayout());
//
Add the subtotal label and a label saying
//
that it is the subtotal.
TotalPanel.add("North", new Label("Total: "));
TotalPanel.add("South",TotalLabel);
ProductPanelLayout.setConstraints(TotalPanel,
InProductPanelConstraints);
ProductPanel.add(TotalPanel);
ProductPanelLayout.setConstraints(TotalPanel,
InProductPanelConstraints);
// Add the embedded panel to the Product Panel.
ProductPanel.add(TotalPanel);
// Set the constraints for the Product Panel's insertion.
PrimaryLayout.setConstraints(ProductPanel,
ProductPanelConstraints);
// Add the Product Panel to the frame.
add(ProductPanel);
// The second panel to be embedded in
the frame is the Info panel.
// This panel gets the information about the user.
GridBagLayout InfoPanelLayout = new GridBagLayout();
Panel InfoPanel = new Panel();
GridBagConstraints InfoPanelConstraints
= new GridBagConstraints();
InfoPanelConstraints.gridwidth = GridBagConstraints.REMAINDER;
ProductPanelLayout.setConstraints(InfoPanel,
InfoPanelConstraints);
InfoPanel.setLayout(InfoPanelLayout);
GridBagConstraints
InInfoConstraints = new GridBagConstraints();
InInfoConstraints.gridwidth
= GridBagConstraints.REMAINDER;
InInfoConstraints.anchor
= GridBagConstraints.WEST;
Label
InfoLabel = new Label("Your information: ");
InfoPanelLayout.setConstraints(InfoLabel,
InInfoConstraints);
InfoPanel.add(InfoLabel);
// The name entry field area.
Panel
NameFieldPanel = new Panel();
NameFieldPanel.setLayout(new
BorderLayout());
NameFieldPanel.add("West",new
Label("Name:"));
NameFieldPanel.add("East",NameEntryField);
InInfoConstraints.anchor
= GridBagConstraints.EAST;
InfoPanelLayout.setConstraints(NameFieldPanel,
InInfoConstraints);
InfoPanel.add(NameFieldPanel);
// The Street entry area implementation.
Panel
StreetFieldPanel = new Panel();
StreetFieldPanel.setLayout(new
BorderLayout());
StreetFieldPanel.add("West",new
Label("Street:"));
StreetFieldPanel.add("East",StreetEntryField);
InfoPanelLayout.setConstraints(StreetFieldPanel,
InInfoConstraints);
InfoPanel.add(StreetFieldPanel);
Panel
CityFieldPanel = new Panel();
CityFieldPanel.setLayout(new
BorderLayout());
CityFieldPanel.add("West",new
Label("City:"));
EntryFieldPanel.add("East",CityEntryField);
InfoPanelLayout.setConstraints(CityFieldPanel,
InInfoConstraints);
InfoPanel.add(CityFieldPanel);
// The zip entry field implementation.
Panel
ZipFieldPanel = new Panel();
ZipFieldPanel.setLayout(new
BorderLayout());
ZipFieldPanel.add("West",new
Label("Zip:"));
ZipFieldPanel.add("East",ZipEntryField);
InfoPanelLayout.setConstraints(ZipFieldPanel,
InInfoConstraints);
InfoPanel.add(ZipFieldPanel);
// The comment label.
InInfoConstraints.anchor
= GridBagConstraints.WEST;
Label
CommentLabel = new Label("Comments: ");
InfoPanelLayout.setConstraints(CommentLabel,
InInfoConstraints);
InfoPanel.add(CommentLabel);
// Add the comment box.
InInfoConstraints.anchor
= GridBagConstraints.CENTER;
InfoPanelLayout.setConstraints(CommentTextArea,
InInfoConstraints);
InfoPanel.add(CommentTextArea);
PrimaryLayout.setConstraints(InfoPanel,
InfoPanelConstraints);
// Add the info panel to the frame layout.
add(InfoPanel);
// Add and create the repeat customer checkbox.
Panel
ContactPanel = new Panel();
ContactPanel.setLayout(new
BorderLayout());
// Add a label to the ContactMethodGroup.
ContactPanel.add("North",new
Label("How
would you like to be contacted? "));
// Declare the CheckboxGroup, and allocate space.
CheckboxGroup ContactMethodGroup;
ContactMethodGroup = new CheckboxGroup();
// Create some checkboxes to put in the group.
Checkbox EmailBox = new Checkbox("Email",ContactMethodGroup,true);
Checkbox PhoneBox = new
Checkbox("Phone",ContactMethodGroup,false);
Checkbox MailBox = new
Checkbox("US
Mail",ContactMethodGroup,false);
// Add the checkboxes into the applet
panel.
ContactPanel.add("West",EmailBox);
ContactPanel.add("Center",PhoneBox);
ContactPanel.add("East",MailBox);
// Sets the constraints for the Contact panel.
GridBagConstraints
ContactPanelConstraints = new GridBagConstraints();
ContactPanelConstraints.gridwidth
= 2;
GridBagConstraints.RELATIVE;
ContactPanelConstraints.weightx
= 2.0;
PrimaryLayout.setConstraints(ContactPanel,
ContactPanelConstraints);
add(ContactPanel);
// Insert the different checkboxes into the panel.
GridBagConstraints CustCheckBoxConstraints
= new GridBagConstraints();
CustCheckBoxConstraints.weightx =1.0;
CustCheckBoxConstraints.gridwidth = GridBagConstraints.REMAINDER;
Checkbox RepeatCustCheckBox = new Checkbox("Repeat Customer?");
PrimaryLayout.setConstraints(RepeatCustCheckBox,
CustCheckBoxConstraints);
add(RepeatCustCheckBox);
GridBagConstraints ButtonConstraints = new GridBagConstraints();
ButtonConstraints.gridx = GridBagConstraints.RELATIVE;
// Spreads the buttons out across the
window.
ButtonConstraints.weightx = 1.0;
ButtonConstraints.weighty = 1.0;
// Declare, set, and add the "Submit"
button.
SubmitButton = new Button("Submit");
PrimaryLayout.setConstraints(SubmitButton,
ButtonConstraints);
add(SubmitButton);
// Declare, set, and add the "Clear" button.
ClearButton = new Button("Clear");
PrimaryLayout.setConstraints(ClearButton, ButtonConstraints);
add(ClearButton);
// Set the constraints and insert the
Quit button. This button
// due to the REMAINDER setting will be the last on the line.
GridBagConstraints LastButtonConstraints
= new GridBagConstraints();
LastButtonConstraints.gridwidth = GridBagConstraints.REMAINDER;
QuitButton = new Button("Quit");
PrimaryLayout.setConstraints(QuitButton, LastButtonConstraints);
add(QuitButton);
// Method which resets all of the internal
values.
resetValues();
}
In this chapter, you covered a good amount of ground. First, you
saw the specifics of a number of the different containers available
in the AWT, such as the Frame
class and the Panel class.
You also saw how the Applet
class is a descendant of the Panel
class. You learned how to manipulate windows from inside your
programs and also how to set the menu bar in those windows. Next,
you saw how to create dialog boxes using the AWT, and you included
these boxes in the Order Entry System. Finally, you learned how
to use the different layout managers in the AWT, and you included
those in the Order Entry System.
Perhaps the most recognized fact about Java is that it can bring
the Web alive. Many lay people believe that Java is "just
the motion on the Web." This fact says something about Java
and its appeal: graphics and animation. The next chapter covers
the basic graphical functions of Java and takes the first steps
toward creating animation, covered in depth later in this book.
In the next chapter, the graphical functions and capabilities
of Java are added to the Order Entry System, and an imported logo
is placed upon the head of the frame. These capabilities are used
to incorporate some graphics into the Order Entry System interface.
Next
Previous
Contents
|