More About Containers
Dialogs
Adding to the Order Entry System
Layout Managers in the AWT
Fixing the Layout of the Order Entry System
by Michael Girdley
This chapter is going to cover much information. First, it further explores the concepts of containers in the Java AWT. It cover 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. And since containers are components, containers can hold other containers. When you imbed 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
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 we 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 we 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 (such as 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.
** 08wpj01 **
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.
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 imbedded 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 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.
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 of 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. } }
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.
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 4 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 5 and 6 declare and initialize two instances of the Frame class using the constructors described previously. Line 10 sets the title for the AFrame frame and line 14 resizes the BFrame frame to be 300 pixels wide by 250 pixels high. And finally, line 17 displays the BFrame using the show method of the frame class. But, where is the AFrame declared and initialized in line 5? 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. It is covered in the next section.
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.
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.
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 off your last "}", declare another class called something like FrameJr and so forth. 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 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.
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.
This method of re-construction of your classes is not limited to frames. It works for any class. For example, you wish to create a version of the String class whose constructor accepts a string and removed 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.
Another important method you can use with the Frame class is the setResizeable(boolean) method. This method either turns on or turns off the ability 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 if they wish.
One of the most interesting feature of frames in the AWT is the ability 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.
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 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 either 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:
To visually help you grasp the organization of menu bars, Figure 8.3 is a typical menu hierarchy of insertion.
** 08wpj03 **
Figure 8.3. A typical menu hierarchy of insertion.
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.
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.
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 java\src\awt\Frame.java.
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.
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 their methods. As mention before, both the Frame class and the Dialog class use the getResizeable() and setResizeable(booleana) 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.
Remember, for every class which is a descendant of the Window class (including the Frame, Dialog, and FileDialog (covered next), 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.
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 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); public void init () { // Resize the BFrame to width of 100 pixels, // And a height of 150 pixels. AFrame.resize(150, 100); // Resize each of the dialogs so we 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.
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 BFrame to width of 100 pixels, // And a height of 150 pixels. Frame.resize(150, 100); // Resize each of the dialogs so we 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) { Dialog.show(); } return super.handleEvent(InEvent); } } class FrameJr extends Frame { FrameJr (String InTitle) { super(InTitle); } }
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.
Figure 8.4. The output from the DialogCrazee applet.
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(); } . .
In terms of writing applets, a special dialog subclass 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.
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 a 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:
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 our 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(); // Disply 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 us to utilize a frame in the applet. */ class OrderEntryFrameType extends Frame { // This is the constructor for our 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); // AddItems 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(); // AddItems 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 we'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 their 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 user 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.
** 08wpj05.pcx **
Figure 8.5. The Order Entry System from the Appletviewer utility.
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 created 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.
** 08wpj07.pcx **
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.
**08wpj08.pcx **
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 then applies one to the Order Entry System.
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.
The following 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 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 right 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.
** 08wpj09.pcx **
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 mangers 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. Then, 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.
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.
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.
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:
GridBagLayout GBL = new GridBagLayout(); setLayout(GBL);
Where GBL is the local instance of the GridBagLayout class.
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.
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 being 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.
And 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.
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. So, a component with a weightx of 3 has a size three times that of a component which has 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 a empty area around your component.
The following steps outline the steps in implementing the GridBagLayout Manager for a container:
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.
** 08wpj10.pcx **
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 ProductPanel, which will contain product // choices, sizes, etc. GridBagConstraints ProductPanelConstraints = new GridBagConstraints(); // The productpanel 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); // AddItems 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 imbedded panel to the product panel. InProductPanelConstraints.anchor = GridBagConstraints.NORTH; ProductPanelLayout.setConstraints( ListPanel, InProductPanelConstraints); ProductPanel.add(ListPanel); // Another panel which will be imbedded 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(); // AddItems 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 imbedded panel to the product panel. ProductPanelLayout.setConstraints(SizePanel, InProductPanelConstraints); ProductPanel.add(SizePanel); // Another panel which will be imbedded 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 imbedded 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 imbedded panel to the product panel. ProductPanelLayout.setConstraints(AmountPanel, InProductPanelConstraints); ProductPanel.add(AmountPanel); // The last panel which will be imbedded 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 imbedded 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 imbedded 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.