Because of the popularity of Microsoft Windows and Apple Macintosh systems, computer users have come to expect certain things from their software. It should use a graphical user interface, be controllable with a mouse, and work like a lot of their other programs do. These expectations are a far cry from the heyday of MS-DOS and other command-line systems, when the user interface varied greatly with each program you used and point-and-click was something photographers did.
Today's programs that use a graphical user interface and mouse control are called windowing software. Although you've been using a command-line interface to write Java programs, you can create windowing programs using a group of classes called the Abstract Windowing Toolkit (AWT). You'll learn how to create a windowing program during this hour.
The following topics will be covered:
Because Java is a cross-platform language that enables you to write programs for many different operating systems, its windowing software must be flexible. Instead of catering only to the Microsoft Windows-style of windowing or the Apple Macintosh version, it must handle both, along with other platforms. The Abstract Windowing Toolkit gets its name because it is a set of classes intended to work with any platform that runs Java programs. This approach was needed so that programmers could offer their applets on the World Wide Web, which is used by people on dozens of different types of computers, operating systems, and Web browsers.
The Toolkit classes include everything you need to write programs that use a GUI (pronounced gooey). If you think a GUI is the brother of Huey, Louie, and Dewey, know that the acronym stands for graphical user interface. With Java's windowing toolkit, you can create a GUI that includes all of the following:
The Toolkit also includes classes that you have been using up to this point to offer fonts, color, and graphics in your programs. Another element of the Toolkit you'll be learning about during Hour 20, "Responding to User Events," is how the Toolkit can be used to receive mouse clicks and other user input.
To use components such as buttons and text fields in a Java program, you create a component object and use the add() method to add it to an existing component. For example, a Button component is a clickable button with a label that describes what clicking the button will do. One of the most basic ways to use a component such as a button is to add it to an applet. You can add a button to an applet with two statements, one to create the Button object and one to add it to the applet itself. The following short Java applet will do this:
import java.awt.*; public class ShowButton extends java.applet.Applet { Button panicButton = new Button("Panic"); public void init() { add(panicButton); }
}
The panicButton object is created as an object variable so that you can use it in all methods of the applet program. The argument used with new Button specifies the label of the button. The add(panicButton); statement adds the Button component to the ShowButton applet. Figure 19.1 shows what the output of this program would be.
Figure 19.1. A Button component.
Each of the user components available as part of the Abstract Windowing Toolkit can be added in this manner.
Because so many different things must be introduced during this hour, the full source code used to create each figure is not listed here. You can find full versions of each program on the book's CD-ROM in the Win95nt4/Book/Source/Hour19 directory or on this book's Web site at http://www.prefect.com/java24. Choose the Hour 19's programs link from the front page.
A Label component displays a string that cannot be modified by the user. These components get their name from their usefulness as a way to label other components in an interface. They often are used to identify text fields. A TextField component is an area where a user can enter a single line of text. You can set up the width of the box when you create the text field.
The following statements create a Label component and TextField object and add them to an applet:
Label eMailLabel = new Label("E-mail address: ", Label.RIGHT); TextField eMailAddress = new TextField(25); add(eMailLabel); add(eMailAddress);
Figure 19.2 shows this label and text field side-by-side. Both of the statements in this example use an argument to configure how the component should look. The eMailLabel label is set up with the text E-mail address: and a Label.RIGHT argument. This last value indicates that the label should appear flush right. Label.LEFT aligns the label text flush left, and Label.CENTER centers it. The argument used with TextField indicates that the text field should be approximately 25 characters wide. You also can specify default text that will appear in the text field with a statement such as the following:
TextField state = newTextField("TX", 2);
This statement would create a TextField object that is two characters wide and has the text TX in the field.
Figure 19.2. Label and TextField components.
A Checkbox component is a box next to a line of text that can be checked or unchecked by the user. The following statements create a Checkbox object and add it to an applet:
Checkbox jumboSize = new Checkbox("Jumbo Size"); add(jumboSize);
The argument to the Checkbox() constructor method indicates the text to be displayed alongside the box. If you wanted the box to be checked, you could use the following statement instead:
Checkbox jumboSize = new Checkbox("Jumbo Size", true);
A Checkbox can be presented singly or as part of a group. In a group of check boxes, only one can be checked at a time. To make a Checkbox object part of a group, you have to create a CheckboxGroup object. Consider the following:
CheckboxGroup meals = new CheckboxGroup(); Checkbox frogLegs = new Checkbox("Frog Leg Grande", true, meals); Checkbox fishTacos = new Checkbox("Fish Taco Platter", false, meals); Checkbox emuNuggets = new Checkbox("Emu Nuggets", false, meals); add(frogLegs); add(fishTacos); add(emuNuggets);
This code creates three check boxes that are all grouped under the CheckboxGroup object called meals. The Frog Leg Grande box is checked initially, but if the user checked one of the other meal boxes, the check next to Frog Leg Grande would disappear automatically. Figure 19.3 shows the different check boxes from this section.
Figure 19.3. Checkbox components.
A Choice component is a pop-up list of choices from which a single choice can be made. It serves a similar purpose to a group of check boxes, except that only one of the selections is visible unless the pop-up list is being displayed.
To create a Choice object, you have to add each of the choices after creating the object, as in the following example:
Choice profession = new Choice(); profession.add("Butcher"); profession.add("Baker"); profession.add("Candlestick maker"); profession.add("Fletcher"); profession.add("Fighter"); profession.add("Technical writer"); add(profession);
This example creates a single Choice component that provides six choices for the user to select from. When one is selected, it appears in the display of the component. Figure 19.4 shows this example while the pop-up list of choices is being displayed.
Figure 19.4. A Choice component.
A TextArea component is a text field that enables the user to enter more than one line of text. You can specify the width and height of the component. For example, the following statements create a TextArea component with an approximate width of 50 characters and a height of 10 lines and then add the component to an applet:
TextArea comments = new TextArea("", 10, 50); add(comments);
You can specify a string in the TextArea() constructor method to be displayed in the text area. You can use the newline character \n to send text to the next line, as in the following:
TextArea desire = new TextArea("I should have been a pair\nof ragged claws.", 10, 25);
If the user enters text that extends beyond the component's area, scrollbars will become active on the sides of the component, as shown in Figure 19.5. This TextArea is 10 lines tall and approximately 50 characters wide.
Figure 19.5. A TextArea component.
The last of the components you'll learn to create during this hour are Panel objects. Panel objects are part of of a broader category of objects known as containers. Panel objects don't display anything. Instead, they are used to contain other components. The purpose of Panel objects is to subdivide a display area into different groups of components. When the display is divided into sections, you can use different rules for how each section is displayed on-screen.
You can create a Panel object and add it to an applet with the following statements:
Panel topRow = new Panel(); add(topRow);
When you place components onto an applet or some other kind of container, the way they are organized on-screen is highly variable. The layout of buttons, text fields, and other components can be affected by the following things:
There are several layout managers that you can use to affect how components are shown. The default manager is the FlowLayout class, which is what has been used for all of the examples shown up to this point. Under FlowLayout, components are dropped onto an area in the same way words are organized on a printed page--from left to right, and on to the next line when there's no more space.
To set up an applet to work under FlowLayout, create a FlowLayout object and then use it as an argument to the setLayout() method:
FlowLayout topLayout = new FlowLayout(); setLayout(topLayout);
You also can set up a layout manager to work within a specific container, such as a Panel object. You can do this by using the setLayout() method of that container object. The following statements create a Panel object called inputArea and set it up to use FlowLayout as its layout manager:
Panel inputArea = new Panel(); FlowLayout inputLayout = new FlowLayout(); inputArea.setLayout(inputLayout);
To give you an idea of how the different layout managers work, a simple applet will be shown under each of the classes. The Crisis applet has a graphical user interface with five buttons. Load your word processor and open up a new file called Crisis.java. Enter Listing 19.1, and save the file when you're done.
1: import java.awt.*; 2: 3: public class Crisis extends java.applet.Applet { 4: Button panicButton = new Button("Panic"); 5: Button dontPanicButton = new Button("Don't Panic"); 6: Button blameButton = new Button("Blame Others"); 7: Button mediaButton = new Button("Notify the Media"); 8: Button saveButton = new Button("Save Yourself"); 9: 10: public void init() { 11: add(panicButton); 12: add(dontPanicButton); 13: add(blameButton); 14: add(mediaButton); 15: add(saveButton); 16: } 17: }
After saving the source file Crisis.java, you need to create a simple Web
page that will display this applet. Create a new file called Crisis.html
and enter Listing 19.2.
1: <applet code="Crisis.class" height=228 width=308> 2: </applet>
Save the Web page, and then compile the Crisis.java file with the javac
compiler tool. This applet does not specify a layout manager to use, so the rules
default to FlowLayout. Use appletviewer to load the Web page, and
you should see something resembling Figure 19.6.
The FlowLayout class uses the dimensions of its container as the only guideline for how to lay out components. Resize the window of appletviewer as it is, showing the Crisis applet. Make the window twice as wide, and you'll see all of the Button components now are shown on the same line. Java programs that use the Abstract Windowing Toolkit often will behave differently when their display area is resized.
Figure 19.6. The Crisis applet with all of its components laid out under the FlowLayout class.
The GridLayout class organizes all components in a container into a specific number of rows and columns. All components are allocated the same amount of space in the display area. To see the Crisis applet with a grid layout, load the file Crisis.java back into your word processor and edit the init() method. Right after the public void init() { statement, add the following statements:
GridLayout crisisLayout = new GridLayout(2, 3); setLayout(crisisLayout);
Save and compile the new version of Crisis.java and load the Crisis.html Web page back into appletviewer. The output should resemble Figure 19.7.
Figure 19.7. The Crisis applet with all of its components laid out under the GridLayout class.
GridLayout places all components as they are added into a place on a grid. Components are added from left to right until a row is full, and then the leftmost column of the next grid is filled.
The last layout manager left to experiment with is the BorderLayout class. Return to the Crisis.java file in your word processor, and replace the init() method with the following statements:
public void init() { BorderLayout crisisLayout = new BorderLayout(); setLayout(crisisLayout); add(panicButton, "North"); add(dontPanicButton, "South"); add(blameButton, "East"); add(mediaButton, "West"); add(saveButton, "Center"); }
After you save the change and recompile the Crisis applet, the page you load with the appletviewer should resemble Figure 19.8.
Figure 19.8. The Crisis applet with all of its components laid out under the BorderLayout class.
The BorderLayout manager arranges components into five areas: four denoted by compass directions and one for the center area. When you add a component under this layout, the add() method includes a second argument to specify where the component should be placed. The strings "North", "South", "East", "West", and "Center" are used for this argument.
Like the GridLayout class, BorderLayout devotes all available space to the components. The component placed in the center is given all space that isn't needed for the four border components, so it usually is the largest.
The layout managers that you have seen thus far were applied to an entire applet; the setLayout() method of the applet was used, and all components followed the same rules. This setup can be suitable for some programs, but as you try to develop a graphical user interface with the Abstract Windowing Toolkit, you often will find that none of the layout managers fits. One way around this problem is to use a group of Panel objects as containers to hold different parts of the applet window. You can set up different layout rules for each of these parts by using the setLayout() methods of each Panel object.
This hour's workshop will be to develop a full interface for the program that you will write during the next hour, "Responding to User Events." The program is a Lotto number cruncher that will assess a user's chance of winning one of the multimillion-dollar Lotto contests in the span of a lifetime. This chance will be determined by running random six-number Lotto drawings again and again until the user's numbers turn up as a big winner. Figure 19.9 shows the GUI that you will be developing for the applet.
Figure 19.9. The LottoGUI applet.
Create a new file in your word processor called LottoGUI.java. Enter Listing 19.3, and save the file when you're done.
1: import java.awt.*; 2: 3: public class LottoGUI extends java.applet.Applet { 4: // set up row 1 5: Panel row1 = new Panel(); 6: CheckboxGroup option = new CheckboxGroup(); 7: Checkbox quickpick = new Checkbox("Quick Pick", option, true); 8: Checkbox personal = new Checkbox("Personal",option, false); 9: // set up row 2 10: Panel row2 = new Panel(); 11: Label numbersLabel = new Label("Your picks: ", Label.RIGHT); 12: TextField[] numbers = new TextField[6]; 13: Label winnersLabel = new Label("Winners: ", Label.RIGHT); 14: TextField[] winners = new TextField[6]; 15: // set up row 3 16: Panel row3 = new Panel(); 17: Button stop = new Button("Stop"); 18: Button play = new Button("Play"); 19: Button reset = new Button("Reset"); 20: // set up row 4 21: Panel row4 = new Panel(); 22: Label got3Label = new Label("3 of 6: ", Label.RIGHT); 23: TextField got3 = new TextField(); 24: Label got4Label = new Label("4 of 6: ", Label.RIGHT); 25: TextField got4 = new TextField(); 26: Label got5Label = new Label("5 of 6: ", Label.RIGHT); 27: TextField got5 = new TextField(); 28: Label got6Label = new Label("6 of 6: ", Label.RIGHT); 29: TextField got6 = new TextField(10); 30: Label drawingsLabel = new Label("Drawings: ", Label.RIGHT); 31: TextField drawings = new TextField(); 32: Label yearsLabel = new Label("Years: ", Label.RIGHT); 33: TextField years = new TextField(); 34: 35: public void init() { 36: GridLayout appletLayout = new GridLayout(5, 1, 10, 10); 37: setLayout(appletLayout); 38: 39: FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER, 10, 10); 40: row1.setLayout(layout1); 41: row1.add(quickpick); 42: row1.add(personal); 43: add(row1); 44: 45: GridLayout layout2 = new GridLayout(2, 7, 10, 10); 46: row2.setLayout(layout2); 47: row2.setLayout(layout2); 48: row2.add(numbersLabel); 49: for (int i = 0; i < 6; i++) { 50: numbers[i] = new TextField(); 51: row2.add(numbers[i]); 52: } 53: row2.add(winnersLabel); 54: for (int i = 0; i < 6; i++) { 55: winners[i] = new TextField(); 56: winners[i].setEditable(false); 57: row2.add(winners[i]); 58: } 59: add(row2); 60: 61: FlowLayout layout3 = new FlowLayout(FlowLayout.CENTER, 10, 10); 62: row3.setLayout(layout3); 63: row3.add(stop); 64: row3.add(play); 65: row3.add(reset); 66: add(row3); 67: 68: GridLayout layout4 = new GridLayout(2, 3, 20, 10); 69: row4.setLayout(layout4); 70: row4.add(got3Label); 71: got3.setEditable(false); 72: row4.add(got3); 73: row4.add(got4Label); 74: got4.setEditable(false); 75: row4.add(got4); 76: row4.add(got5Label); 77: got5.setEditable(false); 78: row4.add(got5); 79: row4.add(got6Label); 80: got6.setEditable(false); 81: row4.add(got6); 82: row4.add(drawingsLabel); 83: drawings.setEditable(false); 84: row4.add(drawings); 85: row4.add(yearsLabel); 86: years.setEditable(false); 87: row4.add(years); 88: add(row4); 89: } 90: }
Compile this file with the javac compiler tool, and return to your word
processor to create a Web page for this applet. Create a new file called LottoGUI.html
and enter Listing 19.4. Save the file when you're done.
1: <html> 2: <head> 3: <title>Lotto Madness</title> 4: </head> 5: <body bgcolor="#4b4b4b"> 6: <applet code="LottoGUI.class" width=550 height=270> 7: </applet> 8: </body> 9: </html>
Try this Web page out with the appletviewer tool, and you'll get a chance
to see how the LottoGUI applet will work. Even though you haven't added
any statements that make the program do anything yet, you can make sure that the
graphical interface does what you need it to do.
This applet uses several different layout managers. If you look carefully at each of the components, you might be able to determine which manager is in use in the different areas of the program. To get a clearer picture of how the applet is laid out, take a look at Figure 19.10. The interface is divided into five horizontal rows. Each of these rows is a Panel object, and the overall layout manager of the applet organizes these rows into a GridLayout of five rows and one column.
Figure 19.10. The way the LottoGUI class is organized.
Within the rows, different layout managers are used to determine how the components should appear. Rows 1 and 3 use FlowLayout objects. Line 39 of the program shows how these objects are created:
FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
Three arguments are used with the FlowLayout() constructor method. The first argument, FlowLayout.CENTER, indicates that the components should be centered within their container--the horizontal Panel they are placed on. The last two components specify the width and height each component should be moved away from other components. Using a width of 10 pixels and a height of 10 pixels puts a small amount of extra distance between the components.
Row 2 of the applet is laid out into a grid that is two rows tall and seven columns wide. The GridLayout() constructor also specifies that components should be set apart from other components by 10 pixels in each direction. Lines 45 and 46 set up this grid:
GridLayout layout2 = new GridLayout(2, 7, 10, 10); row2.setLayout(layout2);
Row 4 uses GridLayout to arrange components into a grid that is two rows tall and six columns wide.
The LottoGUI applet uses several of the components described during this hour. Lines 4-33 are used to set up objects for all of the components that make up the interface. The statements are organized by row. First, a Panel object for the row is created, and then each component that will go on the row is set up. This code creates all of the components and containers, but they will not be displayed unless an add() method is used to put them onto the display area.
In Lines 36-88, the components are added. Lines 39-43 are indicative of the entire init() method:
FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER, 10, 10); row1.setLayout(layout1); row1.add(quickpick); row1.add(personal); add(row1);
After a layout manager object is created, it is used with the setLayout() method of the row's Panel object--row1 in this case. Once the layout has been specified, components are added to the Panel object by using its add() method. Once all of the components have been placed, the entire row1 object is added to the applet window using its own add() method.
Users have come to expect a point-and-click, visual environment for the programs that they run. This expectation makes creating software more of a challenge, but Java puts these capabilities into your hands with the windowing toolkit. The Abstract Windowing Toolkit provides all the classes you will need to provide a working, useful GUI in the tradition of Windows and Macintosh software--regardless of what kind of setup you're running Java programs on.
During the next hour, you'll learn more about the function of a graphical user interface. You'll get a chance to see the LottoGUI interface in use as it churns through lottery drawings and tallies up winners.
If your brain hasn't been turned into a GUI mush with this hour's toil, test your skills by answering the following questions.
To interface further with the subject of GUI design, undertake the following activity: