Up until now, your applets and applications have not done much. They have displayed some nice interfaces and you have learned how to manipulate them in your code. Today, we are going to bring your Visual J++ applets and applications to life using
dialogs and handling events to manipulate data. Today you'll learn about the following:
This chapter is very long and covers a lot of material. You might want to budget some extra time for this day.
Today, you'll finish up the last bits of the AWT that didn't fit into yesterday's lesson. In addition to all the graphics, events, UI, and layout mechanisms that the AWT provides, it also provides windows, menus, and dialog boxes, which enable you to
create fully featured applications either as part of your applet or independently for standalone Java applications.
The AWT Window class enables you to create windows that are independent of the browser window containing the appletthat is, separate pop-up windows with their own titles, resize handles, and menubars.
It's important to note here that the Window class has nothing to do with Microsoft Windows. The Window class is a generic class that handles windows on any platform.
The Window class provides basic behavior for windows. Most commonly, instead of using the Window class, you'll use Window's subclasses, Frame and Dialog. The Frame class enables you to create a fully functioning window with a menubar. Dialog is a more
limited window for dialog boxes. You'll learn more about dialog boxes later in this section.
To create a frame, use one of the following constructors:
Like panels, frames are containers. You can add other components to them just as you would regular panels, using the add() method. The default layout for windows is BorderLayout:
win = new Frame("My Cool Window"); win.setLayout(new BorderLayout(10, 20)); win.add("North", new Button("Start")); win.add("Center", new Button("Move"));
To set a size for the new window, use the resize() method. To set a location for where the window appears, use the move() method. Note that the location() method can tell you where the applet window is on the screen so that you can pop up the extra
window in a position relative to that window (all these methods are defined for all containers, so you can use them for applets, windows, and the components inside them, subject to the current layout):
win.resize(100, 200); Dimension d = location(); win.move(d.width + 50, d.height + 50);
When you initially create a window, it's invisible. You need to use the show() method to make the window appear on the screen (you can use hide() to hide it again):
win.show();
The following is an example of a simple applet that displays a simple pop-up window. This applet depends on the MyFrame class that you will also need to create. The MyFrame Class should be a separate .java file called MyFrame.java. Save this project
because you will be extending it throughout this chapter.
Now start by creating a new applet to work with. Create a new Project Workspace using the Java Applet Wizard. Name your Project UIApp. Make sure that you select Yes to create a multithreaded applet and select No for animation support.
Once your Project Workspace is created, create a new text file and enter the following code to create the class MyFrame. Save this as MyFrame.java and insert into the project (Insert | Files into Project from the menu). You can omit the comments if you
so wish.
import java.applet.*; import java.awt.*; class MyFrame extends Frame { MyFrame(String title) { super(title); // Call the parent class function to set the title resize(300,300); // set default size this.show(); // show the frame } }
In the UIApp.java file before the class definition, import the MyFrame class:
import MyFrame;
Add a new data member called m_frmFrame that is of type MyFrame:
MyFrame m_frmFrame;
In the UIApp applet init() method, add the following code:
m_frmFrame = new MyFrame( "My Frame Test" );
Compile and run the applet. A single blank pop-up window should be displayed. As you can tell, all this applet does now is display a simple window. By the way, the only way you can stop this applet is to select File | Close (or Exit) from your
browser's menu. Keep reading and some cool functionality will be added.
Each new window you create can have its own menubar along the top of the screen. Each menubar can have a number of menus, and each menu, in turn, can have menu items. The AWT provides classes for all these things called, respectively, MenuBar, Menu,
and MenuItem. Creating a menu system using plain Java code is akin to pulling teeth, although you might be forced to if you ever need to maintain older code or code developed with another development environment. Luckily, Visual J++ makes it extremely easy
by using the Resource Editor.
If you still wish to create a menu without using the Resource Editor, you can use the Java API documentation included with Visual J++.
The first step in creating a Menu Resource, like other resources, is to create a Resource Template (File | New | Resource Template) just as you did yesterday. Save this new Resource Template, in the UIApp project directory, as UIApp.rct. To insert a
new Menu resource into the template, do the following:
Save the Resource Template. Run the Java Resource Wizard (Tools | Java Resource Wizard). Insert the newly created file MyMenu.java into your UIApp project.
Figure 13.1. A Menu Item Properties dialog box.
Add the following code to the MyFrame Class. At the top of the file add the line:
import MyMenu;
Under the MyFrame class definition add the line:
MyMenu m_mnuMine;
Under the constructor MyFrame(String title) add these lines of code:
m_menuMine = new MyMenu( this ); m_menuMine.CreateMenu();
Your windowwith a menuwill now display. (See Figure 13.2) Even though you've easily created the window and menu item; it doesn't do very much, other than display. That's because there hasn't been any action assigned to the Exit menu item.
Later in this chapter, we'll assign an action to the menu item event. Try adding some other items to your menu and experimenting with the property page settings.
Figure 13.2. My Frame window showing the File menu item.
Some browsers enable you to indicate a special help menu, which will display on the right side of the window's menubar. You can indicate that a specific menu is the help menu by calling the setHelpMenu method of the class MenuBar. You can view the
MyMenu file created by the Java Resource Wizard to determine what data members represent which menu items.
mb.setHelpMenu(ID_HELP);
If, for any reason, you want to prevent a user from selecting a menu item or menu command, you can use the disable() command on the menu ID (and the enable() command to make it available again). When a menu item or command is disabled, it still appears
on the menu; it is, however, grayed-out and unselectable by the user:
ID_HELP.disable();
When you use many Windows applications such as word-processing, spreadsheet, databases, and mail systems, the menu systems are quite elaborate. Often you open a single menu and if you select a given item, another menu opens. A simple example of this is
the Start menu in Windows 95 or Windows NT 4.0. This kind of menu is called a pop-up menu.
To create a pop-up in Visual J++, it is a simple matter of setting properties in the Resource Editor. Follow the preceding steps listed (in the Creating a Menu Resource Item section) to create a new menu resource. Create a new child menu under the File
menu and label it Test. View the properties of the Test item and check the Pop-up box. Immediately, a new pop-up menu appears to which you can add more menu items.
Another menu item that is often used to make menu systems easier to read is a separator bar. As with all pop-ups, adding a separator bar is as simple as checking a box in the properties page of a menu item. In this same little Test resource, add a new
menu item under the Test item. Don't bother with a label or an ID, but simply view the properties and check Separator box. There you go: instant Separator bar.
Dialog boxes are functionally similar to frames in that they pop up new windows on the screen. However, dialog boxes are intended to be used for transient windowsfor example, windows that let you know about warnings, windows that ask you for
specific information, and so on. Dialog boxes don't usually have titlebars (although you can create one with a titlebar) or many of the more general features that windows have. Dialog boxes can also be made non-resizable or modal.
A modal dialog box prevents input to any of the other windows in the applet or application until that dialog box is dismissed.
The AWT provides two kinds of dialog boxes: the Dialog class, which provides a generic dialog box, and FileDialog, which produces a platform-specific dialog box to choose files to save or open.
To create a generic dialog box, use one of these constructors:
Note that because you have to give a dialog box a Frame argument, you can attach dialog boxes only to windows that already exist independently of the applet itself.
The dialog box window, like the frame window, is a panel on which you can lay out and draw UI components and perform graphic operations, just as you would any other panel. Like other windows, the dialog box is initially invisible, but you can show it
with show() and hide it with hide().
Now add a dialog box to that same example with the pop-up window that we have been working with: UIApp. You are simply going to modify the MyFrame class to attach a dialog box that you will define in the Resource Editor. You are also going to attach a
dialog box to the Frame itself.
To create the DLG_GetData dialog box, do the following.
See Figure 13.3 for the completed dialog box.
The default font size for dialog boxes is 8 point. This is quite small! Setting the font on the dialog box to 14 sets the font size for all controls to 14 point.
Figure 13.3. Completed DLG_GetData Dialog box, showing the Edit Box control and OK Button control.
Now your going to create a new dialog box called DLG_ShowData. This new dialog box will be created in the same UIApp.rct file as DLG_GetData.
To create the DLG_ShowData, do the following:
There should be three resources in the resource file: DLG_ShowData, DLG_GetData, and MyMenu. To complete the Resource phase of this example, do the following:
In the MyFrame class, add the following lines of code:
import DLG_GetData; import DLG_ShowData;
Under the MyFrame class definition add the lines:
Font m_Font; DLG_GetData m_dlgGet; DLG_ShowData m_dlgShow; Dialog m_dlgGetDlg;
In the constructor of MyFrame, before Show(), add the following lines of code:
m_Font = new Font("Arial", Font.PLAIN, 18); setFont(m_Font); // Create the ShowData dialog on the Frame; setBackground(Color.lightGray); m_dlgShow = new DLG_ShowData( this ); m_dlgShow.CreateControls(); // Create the GetData dialog Box m_dlgGetDlg = new Dialog ( this, "Data Dialog", false); // Create new generic Dialog object m_dlgGetDlg.setBackground(color.lightGray); m_dlgGetDlg.resize(300,300); m_dlgGetDlg.setFont( m_Font ); // Create the Resource File generated Dialog m_dlgGet = new DLG_GetData(m_dlgGetDlg); m_dlgGet.CreateControls(); // display the two windows; show() m_dlgGetDlg.show();
It might seem unnecessary to add the line of code m_dlgGetDlg.setFont( m_Font );. But, without it, the applet doesn't run. This might be a bug in VJ++we don't know.
To see all of your great work, compile and then run it. (See Figure 13.4.)
Figure 13.4. The GetData and ShowData dialog boxes in IE.
FileDialog provides a basic file open/save dialog box that enables you to access the file system. The FileDialog class is system-independent, but depending upon the platform, the standard Open File dialog is brought up.
For applets, you can bring up the file dialog box, but due to security restrictions you can't do anything with it (or, if you can do anything, access to any files on the local system is severely restricted). FileDialog is much more useful in standalone applications.
To create a file dialog, use the following constructors:
After you create a FileDialog instance, use show() to display it:
FileDialog fd = new FileDialog(this, "FileDialog"); fd.show();
When the user chooses a file in the file dialog and dismisses it, you can then access the filename they chose by using the getDirectory() and getFile() methods; both return strings indicating the values the user chose. You can then open that file by
using the stream and file handling methods (which you'll learn about next week) to read from or write to that file.
Java events are part of the Java AWT package. An event is the way that the AWT communicates to you, as the programmer, and to other Java AWT components that something has happened. That something can be input from the user (mouse movements or clicks,
keypresses), changes in the system environment (a window opening or closing, the window being scrolled up or down), or a host of other things that might, in some way, be interesting to the operation of the program.
In other words, whenever just about anything happens to a Java AWT component, including an applet, an event is generated. Some events are handled by the AWT or by the browser without your needing to do anything. paint() methods, for example, are
generated and handled by the browserall you have to do is tell the AWT what you want painted when it gets to your part of the window. Some events, however (for example, a mouse click inside the boundaries of your applet), you might need to know
about. Writing your Java programs to handle these kinds of events enables you to get input from the user and have your applet change its behavior based on that input.
Now start with the most common event you might be interested in: mouse clicks. Mouse-click events occur when the user clicks the mouse somewhere in the body of your applet. You can intercept mouse clicks to do very simple thingsfor example, to
toggle the sound on and off in your applet, to move to the next slide in a presentation, or to clear the screen and start overor you can use mouse clicks in conjunction with mouse movements to perform more complex motions inside your applet.
When you click the mouse once, the AWT generates two events: a mouseDown event when the mouse button is pressed, and a mouseUp event when the button is released. Why two individual events for a single mouse action? Because you might want to do
different things for the "down" and the "up." For example, look at a pull-down menu. The mouseDown extends the menu, and the mouseUp selects an item (with mouseDrags betweenbut you'll learn about that one later today). If you have
only one event for both actions (mouseUp and mouseDown), you cannot implement that sort of user interaction.
Handling mouse events in your applet is easyall you have to do is override the proper method definition in your applet. That method will be called when that particular event occurs. Here's an example of the method signature for a mouseDown event:
public boolean mouseDown(Event evt, int x, int y) { ... }
The mouseDown() method (and the mouseUp() method as well) takes three parameters: the event itself and the x and y coordinates where the mouseDown or mouseUp event occurred.
The event argument is an instance of the class Event. All system events generate an instance of the Event class, which contains information about where and when the event took place, the kind of event it is, and other information that you might want to
know about this event. Sometimes having a handle to that event object is useful, as you'll discover later in this section.
The x and the y coordinates of the event, as passed in through the x and y arguments, are particularly nice to know because you can use them to determine precisely where the mouse click took place.
For example, here's a simple method that grabs the current x and y positions when a mouseDown event occurs:
public boolean mouseDown(Event evt, int x, int y) { m_iMousex = x; m_iMousey = y; return true; }
By including this method in an applet, every time the user clicks the mouse inside your applet, the data members m_iMousex and m_iMousey will be updated.
Note that this method, unlike the other system methods you've studied thus far, returns a Boolean value instead of not returning anything (void). This will become important later today when you create user interfaces and then manage input to these
interfaces; having an event handler return true or false determines whether a given UI component can intercept an event or whether it needs to pass it on to the enclosing component. The general rule is that if your method deals with the event, it should
return true.
The second half of the mouse click is the mouseUp() method, which is called when the mouse button is released. To handle a mouseUp event, add the mouseUp() method to your applet. mouseUp() looks just like mouseDown():
public boolean mouseUp(Event evt, int x, int y) { .... }
In this section, you'll create an example of an applet that uses mouse eventsmouseDown events in particular. The Spots applet starts with a blank screen and then sits and waits. When you click the mouse on that screen, a blue dot is drawn. You
can place up to ten dots on the screen. Figure 13.5 shows the Spots applet.
Figure 13.5. The Spots applet.
Start from the beginning and build this applet, starting from the initial class definition:
Because this is a very simple applet, we are not going to use the Resource Editor at all. Leave the UIApp running while you complete this next exercise though, you're going to use it later today.
Create a new Project Workspace and name it Spots. Create a new text file and add the following lines of code to it.
import java.awt.Graphics; import java.awt.Color; import java.awt.Event; public class Spots extends java.applet.Applet { final int MAXSPOTS = 10; int m_iXspots[] = new int[MAXSPOTS]; int m_iYspots[] = new int[MAXSPOTS]; int m_iCurrspots = 0; }
This class uses three other AWT classes: Graphics, Color, and Event. That last class, Event, needs to be imported in any applets that use events. The class has four instance variables: a constant to determine the maximum number of spots that can be
drawn, two arrays to store the x and y coordinates of the spots that have already been drawn, and an integer to keep track of the number of the current spot.
This class doesn't include the implements Runnable words in its definition. As you'll see later as you build this applet, it also doesn't have a run() method. Why not? Because it doesn't actually do anything on its ownall it does is wait for input and then do stuff when input happens. There's no need for threads if your applet isn't actively doing something all the time.
Start with the init() method, which has one line, to set the background to white:
public void init() { setBackground(Color.white); }
Set the background in init(), instead of in paint(), because you really need to set the background only once. Also, since paint() is called repeatedly each time a new spot is added, setting the background color in the paint() method unnecessarily slows
down that method. Putting it here is a much better idea.
The main action of this applet occurs on the mouseDown() method, so add that one now:
public boolean mouseDown(Event evt, int x, int y) { if (m_iCurrspots < MAXSPOTS) addspot(x,y); return true; }
When the mouse click occurs, the mouseDown() method tests to see whether there are less than ten spots. If so, it calls the addspot() method (which you'll write soon). If not, it just prints an error message. Finally, it returns true, because all the
event methods have to return a Boolean value (usually true).
What does addspot() do? It adds the coordinates of the spot to the arrays that store the coordinates, increments the currspots variable, and then calls repaint():
void addspot(int x, int y) { m_iXspots[currspots] = x; m_iYspots[currspots] = y; m_iCurrspots++; repaint(); }
You might be wondering why you have to keep track of all the past spots in addition to the current spot. The reason is because of repaint(): each time you paint the screen, you have to paint all the old spots in addition to the newest spot. Otherwise,
each time you painted a new spot, the older spots would get erased. Now, on to the paint() method:
public void paint(Graphics g) { g.setColor(Color.blue); for (int i = 0; i < m_iCurrspots; i++) { g.fillOval(m_iXspots[i] -10, m_iYspots[i] - 10, 20, 20); } }
Inside paint, you just loop through the spots you've stored in the m_iXspots and m_iYspots arrays, painting each one (actually, painting them a little to the right and upward so that the spots are painted around the mouse pointer rather than below and
to the right).
That's it! That's all you need to create an applet that handles mouse clicks. Everything else is handled for you. You have to add the appropriate behavior to mouseDown() or mouseUp() to intercept and handle that event. Listing 13.1 shows the full text
for the Spots applet.
Listing 13.1. The Spots applet.
1: import java.awt.Graphics; 2: import java.awt.Color; 3: import java.awt.Event; 4: 5: public class Spots extends java.applet.Applet 6: { 7: final int MAXSPOTS = 10; 8: int m_iXspots[] = new int[MAXSPOTS]; 9: int m_iYspots[] = new int[MAXSPOTS]; 10: int m_iCurrspots = 0; 11: 12: public void init() 13: { 14: setBackground(Color.white); 15: } 16: 17: public boolean mouseDown(Event evt, int x, int y) 18: { 19: if (m_iCurrspots < MAXSPOTS) 20: addspot(x,y); 21: return true; 22: } 23: 24: void addspot(int x,int y) 25: { 26: m_iXspots[m_iCurrspots] = x; 27: m_iYspots[m_iCurrspots] = y; 28: m_iCurrspots++; 29: repaint(); 30: } 31: 32: public void paint(Graphics g) 33: { 34: g.setColor(Color.blue); 35: for (int i = 0; i < m_iCurrspots; i++) 36: { 37: g.fillOval(m_iXspots[i] - 10, m_iYspots[i] - 10, 20, 20); 38: } 39: } 40: }
Every time the mouse is moved a single pixel in any direction, a mouse move event is generated. There are two mouse movement events: mouse drags, where the movement occurs with the mouse button pressed down, and plain mouse movements, where the mouse
button isn't pressed.
To manage mouse movement events, use the mouseDrag() and mouseMove() methods.
The mouseDrag() and mouseMove() methods, when included in your applet code, intercept and handle mouse movement events. The mouseMove() method, for plain mouse pointer movements without the mouse button pressed, looks much like the mouse-click methods:
public boolean mouseMove(Event evt, int x, int y) { ... }
The mouseDrag() method handles mouse movements made with the mouse button pressed down (a complete dragging movement consists of a mouseDown event, a series of mouseDrag events for each pixel the mouse is moved, and a mouseUp event when the button is
released). The mouseDrag() method looks like this:
public boolean mouseDrag(Event evt, int x, int y) { ... }
Finally, there are the mouseEnter() and mouseExit() methods. These two methods are called when the mouse pointer enters the applet or when it exits the applet. (In case you're wondering why you might need to know this, it's more useful on components of
user interfaces that you might put inside an applet. You'll learn more about UI tomorrow).
Both mouseEnter() and mouseExit() have similar signaturesthree arguments: the event object and the x and y coordinates of the point where the mouse entered or exited the applet.
public boolean mouseEnter(Event evt, int x, int y) { ... } public boolean mouseExit(Event evt, int x, int y) { ... }
Keyboard events are generated whenever users press a key on the keyboard. By using key events, you can get hold of the values of the keys that were pressed to perform an action or merely to get character input from the users of your applet.
To capture a keyboard event, use the keyDown() method:
public boolean keyDown(Event evt, int key) { ... }
The keys generated by keyDown events (and passed into keyDown() as the key argument) are integers representing ASCII character values, which include alphanumeric characters, function keys, tabs, returns, and so on. To use them as characters (for
example, to print them), you need to cast them to characters:
currentchar = (char)key;
Here's a simple example of a keyDown() method that does nothing but set the data member m_cLastKey to the character value of the key you just typed.
public boolean keyDown(Event evt, int key) { m_cLastKey = (char)key; return true; }
As with mouse clicks, each keyDown event also has a corresponding keyUp event. To intercept keyUp events, use the keyUp() method:
public booklean keyUp(Event evt, int key) { ... }
The Event class provides a set of class variables that refer to several standard non-alphanumeric keys, such as the arrow keys. If your interface uses these keys, you can provide more readable code by testing for these names in your keyDown() method
rather than testing for their numeric values. For example, to test whether the up arrow was pressed, you might use the following code fragment:
if (key == Event.UP) { ... }
Because the values these class variables hold are integers, you also can use the switch statement to test for them.
Table 13.1 shows the standard event class variables for various keys and the actual keys they represent.
Class Variable | Represented Key |
Event.HOME | The Home key |
Event.END | The End key |
Event.PGUP | The Page Up key |
Event.PGDN | The Page Down key |
Event.UP | The up arrow |
Event.DOWN | The down arrow |
Event.LEFT | The left arrow |
Event.RIGHT | The right arrow |
Now look at an applet that demonstrates keyboard events. This one enables you to type a character, it then displays that character in the center of the applet window. You then can move that character around on the screen by using the arrow keys. Typing
another character at any time changes the character as it's currently displayed. Figure 13.6 shows an example.
This applet is actually less complicated than the previous applets you've used. This one has only three methods: init(), keyDown(), and paint(). The data members are also simpler, because the only things you need to keep track of are the x and y
positions of the current character and the values of that character itself. Here's the top of this class definition:
import java.awt.Graphics; import java.awt.Event; import java.awt.Font; import java.awt.Color; public class Keys extends java.applet.Applet { char m_cCurrkey; int m_iCurrx; int m_iCurry; }
The init() method is responsible for three things: setting the background color, setting the applet's font (here, 36 point Helvetica bold), and setting the beginning position for the character (the middle of the screen, minus a few points to nudge it
up and to the right):
public void init() { m_iCurrx = (size().width / 2) - 8; // default m_iCurry = (size().height / 2) - 16; setBackground(Color.white); setFont(new Font("Helvetica", Font.BOLD, 36)); }
Because this applet's behavior is based on keyboard input, the keyDown() method is where most of the work of the applet takes place:
public boolean keyDown(Event evt, int key) { switch (key) { case Event.DOWN: m_iCurry += 5; break; case Event.UP: m_iCurry -= 5; break; case Event.LEFT: m_iCurrx -= 5; break; case Event.RIGHT: m_iCurrx += 5; break; default: m_cCurrkey = (char)key; } repaint(); return true; }
In the center of the keyDown() applet is a switch statement that tests for different key events. If the event is an arrow key, the appropriate change is made to the character's position. If the event is any other key, the character itself is changed.
The method finishes up with a repaint() and returns true.
The paint() method here is almost trivial; just display the current character at the current position. However, note that when the applet starts up, there's no initial character and nothing to draw, so you have to take that into account. The m_cCurrkey
variable is initialized to 0, so you paint the applet only if m_cCurrkey has an actual value:
public void paint(Graphics g) { if (m_cCurrkey != 0) { g.drawString(String.valueOf(m_cCurrkey), m_iCurrx,m_iCurry); } }
Listing 13.2 shows the complete source for the Keys applet:
Listing 13.2. The Keys applet.
1: import java.awt.Graphics; 2: import java.awt.Event; 3: import java.awt.Font; 4: import java.awt.Color; 5: 6: public class Keys extends java.applet.Applet 7: { 8: char m_cCurrkey; 9: int m_iCurrx; 10: int m_iCurry; 11: 12: public void init() 13: { 14: m_iCurrx = (size().width / 2) -8; // default 15: m_iCurry = (size().height / 2) -16; 16: 17: setBackground(Color.white); 18: setFont(new Font("Helvetica",Font.BOLD,36)); 19: } 20: 21: public boolean keyDown(Event evt, int key) 22: { 23: switch (key) 24: { 25: case Event.DOWN: 26: m_iCurry += 5; 27: break; 28: case Event.UP: 29: m_iCurry -= 5; 30: break; 31: case Event.LEFT: 32: m_iCurrx -= 5; 33: break; 34: case Event.RIGHT: 35: m_iCurrx += 5; 36: break; 37: default: 38: m_cCurrkey = (char)key; 39: } 40: 41: repaint(); 42: return true; 43: } 44: 45: public void paint(Graphics g) 46: { 47: if (m_cCurrkey != 0) 48: { 49: g.drawString(String.valueOf(m_cCurrkey), m_iCurrx,m_iCurry); 50: } 51: } 52: }
Shift, control, and meta are modifier keys. They don't generate key events themselves, but when you get an ordinary mouse or keyboard event, you can test to see whether those keys were held down when the event occurred. Sometimes it might be
obviousshifted alphanumeric keys produce different key events than unshifted ones, for example. For other events, howevermouse events in particularyou might want to handle an event with a modifier key held down differently from a regular
version of that event.
In the Windows environment, there is no equivalent to a meta key, so when running a Java program on a Windows system, the metaDown() event will never be triggered by a key press. Even though there is no meta on a Windows system, the metaDown() event is triggered when the right mouse button is clicked.
The Event class provides three methods for testing whether or not a modifier key is held down: shiftDown(), metaDown(), and controlDown(). All return Boolean values based on whether that modifier key is indeed held down. You can use these three methods
in any of the event handling methods (mouse or keyboard) by calling them on the event object passed into that method:
public boolean mouseDown(Event evt, int x, int y ) { if (evt.shiftDown()) // handle shift-click else // handle regular click }
The default methods you've learned about today for handling basic events in applets are actually called by a generic event handler method called handleEvent(). The handleEvent() method is how the AWT generically deals with events that occur between
application components and events based upon user input.
In the default handleEvent() method, basic events are processed and the methods you learned about today are called. To handle events other than those mentioned here, to change the default event handling behavior, or to create and pass your own events,
you need to override handleEvent() in your own Java programs. The handleEvent() method looks like this:
public boolean handleEvent(Event evt) { ... }
To test for specific events, examine the ID data member of the Event object that gets passed in. The event ID is an integer, but fortunately, the Event class defines a whole set of event IDs as class variables that you can test for in the body of the
handleEvent(). Because these class variables are integer constants, a switch statement works particularly well. For example, here's a simple handleEvent() method to print out debugging information about mouse events:
public boolean handleEvent(Event evt) { switch (evt.id) { case Event.MOUSE_DOWN: System.out.println("MouseDown: " + evt.x + "," + evt.y); return true; case Event.MOUSE_UP: System.out.println("MouseUp: " + evt.x + "," + evt.y); return true; case Event.MOUSE_MOVE: System.out.println("MouseMove: " + evt.x + "," + evt.y); return true; case Event.MOUSE_DRAG: System.out.println("MouseDown: " + evt.x + "," + evt.y); return true; default: return false; } }
You can test for the following keyboard events:
You can test for these mouse events:
Note that if you override handleEvent() in your class, none of the default event handling methods you learned about today will get called unless you explicitly call them in the body of handleEvent(), so be careful if you decide to do this. One way to
get around this is to test for the event you're interested in, and if that event isn't it, to call super.handleEvent() so that the superclass that defines handleEvent() can process things. Here's an example of how to do this:
public boolean handleEvent(Event evt) { if (evt.id == Event.MOUSE_DOWN) { // process the mouse down return true; } else { return super.handleEvent(evt); } }
In addition to these events, the Event class has a whole suite of methods for handling the UI components. You'll learn more about these events in the next section.
Now put everything you have learned today together. You have learned how to display windows and dialog boxes, and you have the basics of event handling under your belt. Now it's time to add some life to the UIApp that you created earlier today:
Figure 13.7. GetData Properties box.
For your UI components to do something when they are activated, you need to hook up the UI's action with an operation. Testing for an action by a UI component is a form of event managementthe things you learned yesterday about events will come in
handy here. In particular, UI components produce the special kind of event called an action. To intercept an action by any UI component, you define an action() method in your applet or class:
public boolean action(Event evt, Object arg) { ... }
The action() method should look familiar to the basic mouse and keyboard event methods. Like those methods, it gets passed the event object that represents this event. It also gets an extra object, which can be of any type. What's that second argument
for?
The second argument to the action method depends upon the UI component that's generating the event. The basic definition is that it's any arbitrary argumentwhen a component generates an event, it can pass along any extra information that might be
needed later. Because that extra information might be useful for you, it's passed on through the action() method.
All the basic UI components (except for labels, which have no action) have different actions and arguments:
Note that with actions, unlike with ordinary events, you can have many different kinds of objects generating the event, as opposed to a single event such as a mouseDown. To deal with those different UI components and the actions they generate, you have
to test for the type of object that sent/created the event in the first place inside the body of your action() method. That object is stored in the event's target data member and you can use the instanceof operator to find out what kind of UI component
sent it, as shown in the following code sample:
public boolean action(Event evt, Object arg) { if (evt.target instanceof TextField) { handleText(evt.target); } else if (evt.target instanceof Choice) { handleChoice(arg); } ... }
Although you can handle UI actions in the body of the action() method, it's much more common simply to define a handler method and call that method from action() instead. Here, there are two handler methods: one to handle the action on the text field
(handleText()) and one to handle the action on the choice menu (handleChoice()). Depending upon the action you want to handle, you might also want to pass on the argument from the action, the UI component that sent it, or any other information that the
event might contain.
Now make the UIApp do something other than look pretty. In the MyFrame class, add the following method:
public boolean action(Event evt, Object arg) { if (evt.target instanceof Button) { String Val = (String)arg; if ( Val.compareTo("OK") == 0) { m_dlgShow.ID_DISPLAY_DATA.setText(m_dlgGet.ID_DATA.getText()); m_dlgGetDlg.hide(); return true; } } return false; }
The preceding code traps the event on the OK button in the dialog box. It then checks to see if the caption is OK, and if so, sets the text in the Frame to the same data as the text in the dialog box.
The act of selecting a menu item causes an action event to be generated. You can handle that action the same way you handle other action methodsby overriding action(). Both regular menu items and checkbox menu items have actions that generate an
extra argument representing the label for that menu. You can use that label to determine which action to take. Note, also, that because CheckBoxMenuItem is a subclass of MenuItem, you don't have to treat menu items of type CheckBoxMenuItem as a special
case. Here is an example:
public boolean action(Event evt, Object arg) { if (evt.target instanceof MenuItem) { String label = (String)arg; if (label.equals("Show Coordinates")) toggleCoords(); else if (label.equals("Fill")) fillcurrentArea(); return true; } else return false; }
Now add some more functionality to the UPApp. In the MyFrame class, change the action method to read like the following:
public boolean action(Event evt, Object arg) { String sVal = (String)arg; if (evt.target instanceof Button) { if ( sVal.compareTo("OK") == 0) { m_dlgShow.ID_DISPLAY_DATA.setText(m_dlgGet.ID_DATA.getText()); m_dlgGetDlg.hide(); return true; } } if (evt.target instanceof MenuItem) { if (sVal.equals ("Get Data")) { m_dlgGet.ID_DATA.setText(m_dlgShow.ID_DISPLAY_DATA.getText()); m_dlgGetDlg.show(); return true; } if (sVal.equals ("&Exit")) { m_dlgGetDlg.hide(); hide(); return true; } } return false; }
Recompile your project, and then execute it. Now the UIApp applet should actually do something. When it starts, the frame window and the dialog box are displayed. When you enter some text in the text field and click OK, the text value of the frame is
set to the same value as in the text field of the dialog box. If you change the text in the frame, and then select Edit | Get Data from the menu, the dialog box is displayed again. You can then change the text in the dialog box and continue to repeat the
procedures. From the menu of the frame, you can also select File | Exit to close the windows.
Today, you learned about writing your own event handler methods, and you noted that the Event class defines many standard events for which you can test. Window events are part of that list, so if you use windows, these events might be of interest to
you. Table 13.2 shows those events.
WINDOW_DESTROY | Generated when a window is destroyed (for example, when the browser or applet viewer has quit) |
WINDOW_EXPOSE | Generated when the window is brought forward from behind other windows |
WINDOW_ICONIFY | Generated when the window is minimized to an icon |
WINDOW_DEICONIFY | Generated when the window is restored from an icon |
WINDOW_MOVED | Generated when the window is moved |
To intercept a specific event, you need to test for that event's ID. The available IDs are defined as class variables in the Event class, so you can test for them by name. You learned about some of the basic events today; Table 13.3 shows additional
events that might be useful to you for some of the more common components; other events can be found in the InfoView topic "1.14 Class Event."
Event ID | What It Represents |
ACTION_EVENT | Generated when a UI component action occurs |
KEY_ACTION | Generated when text field action occurs |
LIST_DESELECT | Generated when an item in a scrolling list is deselected |
LIST_SELECT | Generated when an item in a scrolling list is selected |
SCROLL_ABSOLUTE | Generated when a scrollbar's box has been moved |
SCROLL_LINE_DOWN | Generated when a scrollbar's bottom or left endpoint (button) is selected |
SCROLL_LINE_UP | Generated when a scrollbar's top or right endpoint (button) is selected |
SCROLL_PAGE_DOWN | Generated when the scrollbar's field below (or to the left of) the box is selected |
SCROLL_PAGE_UP | Generated when the scrollbar's field above (or to the right of) the box is selected |
Today you finished exploring applets and the AWT by learning about two important concepts. First, you learned about windows, frames, menus, and dialogs, which enable you to create a framework for your appletsor enable your Java applications to
take advantage of applet features.
The second topic was how to handle menu actions and events. Most of the time, all you need to do is stick the right method in your applet code, and your applet intercepts and handles that method. The following are some of the basic events you can
manage in this way:
Q: When I created a dialog box resource, I noticed that a new button bar displayed. What's it used for?
A: The button bar that appears at the bottom of the screen has a number of alignment options that make it easy to align the buttons on your newly created dialog box. Options are also available for sizing the dialog box buttons. At least one
control (and in several cases two or more controls) must be selected before the option(s) become active. Experiment with the options on the button bar. The option on the extreme left of the toolbar (it looks like a light switch) that might be a particular
interest allows you to run the dialog box to test its appearance and behavior.
Q: On the Controls Toolbar, I saw a number of controls I didn't use. What are they used for?
A: There are a number of options available on the Controls Toolbar that make designing a dialog box very easy. The options allow you to easily add check boxes, radio buttons, or a combination boxes with drop-down lists. There are options for
adding scroll bars, hot keys, and sliders. Pictures and animation can also be added using options provided on this rather extensive toolbar. Experiment with the many options and see what you can come up with.
Q: The pop-up windows I create using VJ++ display a warning in my browser that an applet window is running. What does this mean and why does this warning display?
A: Depending on the browser that's used, the applet warning varies, however, the purpose for the warning is the same. The warning displays to tell you (and any users of your applet) that the window being displayed was generated by an applet and
not by the browser itself. This security feature is a good thing; it keeps an applet programmer from popping up a window that masquerades as a browser window and, for example, asks users for their passwords. There's nothing you can do to hide or obscure
the warning.
Q: What good is having a File dialog box if you can't read or write files from the local file system?
A: Depending on the browser, applets often can't read or write from the local file system, but you can use AWT components in Java applications as well as applets, and the File dialog box is very useful for applications.
Q: The mouseDown() and mouseUp() methods seem to apply to only a single mouse button. How can I determine which button on the mouse has been pressed?
A: At the moment, you can't. AWT assumes that you're using a one button mouse , or if you have a mouse with multiple buttons, that it's using only the left one. Although this assumption limits the kinds of actions you can perform in your applet,
it does provide a cross-platform solution. Different systems have different mice, so writing your applet to do something specific with the right mouse button isn't a good idea if the people running your applet are using Macintoshes and have only a one
button mouse. If you really want to have different mouse actions perform different things, test for modifier keys (Alt | Shift) in your mouseDown() and mouseUp() methods.