There are many significant changes between JDK 1.0.2 and JDK 1.1. Perhaps the area of greatest change is in the event handling model. The old model has been completely replaced by a new model. There is little or no resemblance between the Delegation Model used in JDK 1.1 and the Inheritance Model used in JDK 1.0.2.
This lesson will provide a description of the new model along with sample programs that illustrate some aspects of the new model.
Subsequent lessons will deal with the new model in more detail, providing more complex sample programs.
In this and the following sections, we will describe how the new model maps to the AWT API. No attempt will be made to discuss the rationale for the change. You are referred to the JavaSoft site for discussions of that sort.
Please note that much of this information was taken from the documentation released with the various versions of JDK 1.1, and is the intellectual property of Sun Microsystems.
The material is being reproduced here for the sole purpose of assisting students in learning how to use the new event model.
Returning "true" from one of these methods consumes the event so it is not processed further. Otherwise the event is propagated sequentially up the GUI hierarchy until either it is consumed or the root of the hierarchy is reached. The result of this model is that programs have essentially two choices for structuring their event-handling code:
In the inheritance model from version 1.0, there is no filtering of events. Events are always delivered to components regardless of whether the components actually handle them or not. This is a general performance problem, particularly with high-frequency events such as mouse moves. Sun predicts that all systems should see performance improvement as a result of this change with the most improvement being enjoyed by Solaris systems.
|
Also, the previous lesson on callbacks should have given you considerable background to help you understand this material. If you are not familiar with the material in those lessons, you should go back and review that material.
Events are now organized into a hierarchy of event classes.
The new model makes use of event sources and event listeners.
An event source is an object that has the ability to determine when an interesting event has occurred, and to notify listener objects of the occurrence of the event. Although you as the programmer establish the framework for such notification, the actual notification takes place automatically behind the scenes.
A listener object is an instance of a class (or instance of a subclass of a class) that implements a specific listener interface. A number of listener interfaces are defined where each interface declares the methods appropriate for a specific class of events. Thus, there is natural pairing of classes of events and interface definitions.
For example, there is a class of mouse events that includes most of the events normally associated with mouse action and there is a matching interface definition which is used to define a listener class for those events (actually this is the one case where two interfaces are defined to match up with a single event class).
A listener object can be registered on a source object to be notified of the occurrence of all events of the specific class for which the listener object is designed.
Once a listener object is registered to be notified of those events, the occurrence of an event defined by the specified class will automatically invoke the matching method in the listener object. The code in the body of the method is designed by the programmer to perform the desired action when the event occurs.
Some event classes (such as the mouse events, for example) involve a number of different possible event types. A listener class which implements the matching interface for that event class must implement or define (provide a body for) all the methods declared in the interface. To prevent this from being burdensome, an intermediate set of classes, known as Adapter classes, is provided.
These Adapter classes implement the listener interfaces, and define the matching interface methods with empty methods. A listener class can then be defined which extends the Adapter class instead of implementing the interface. When this is done, the listener class need only override those methods of interest since the requirement to define all of the interface methods has already been satisfied by the Adapter class.
For example, in the sample program which follows, two different listener objects instantiated from two different listener classes are registered to receive all events involving the manipulation of a Frame object (opening, closing, minimizing, etc.).
One of the listener classes implements the WindowListener interface and hence must define all six methods of that interface.
The other listener class extends the WindowAdapter class which in turn implements the WindowListener interface. The WindowAdapter class defines all six methods as empty methods. Thus, this listener class can get by with overriding only two of the six methods of the interface.
This program illustrates the use of Event Sources, Event Listeners, and Adapters in the Delegation Event Model.
Briefly, this application instantiates an object which creates a user interface consisting of a simple Frame object. This object is an Event Source which notifies two different Event Listener objects of Window events.
One of the Listener objects implements the WindowListener interface and defines all of the methods declared in that interface.
The other Listener object extends the Adapter class named WindowAdapter. As explained earlier, the purpose of Adapter classes (as used in this context) is to implement the Listener interfaces and to define all of the methods with empty methods. (Adapter classes are viewed in a broader context in the advanced lessons on the Reflection API.)
Classes which extend the Adapter classes can then selectively override only those methods of interest. This Listener object overrides only two of the methods.
Note that this application does not terminate and return control to the operating system. You must forcefully terminate it.
This program was tested using JDK 1.1.3 under Win95.
The output produced by running the program is presented later in this lesson.
public class Event08 {//controlling class public static void main(String[] args){ GUI gui = new GUI();//instantiate a GUInterface object }//end main }//end class Event08 |
This class is used
class GUI{ public GUI(){//constructor //Create a new Frame object Frame displayWindow = new Frame(); displayWindow.setSize(300,200); displayWindow.setTitle("Copyright 1997, R.G.Baldwin"); |
A Frame is a top-level window with a title and a border. The
default layout for a frame is BorderLayout. (We will learn more
about layout managers later)
Frames are capable of generating the following types of window events:
|
Next we will instantiate two Listener objects that will process Window events.
The class definitions, named Wproc1 and Wproc2, for these two classes will follow the discussion of the GUI class.
Note that we are passing a reference to the Frame object to the
constructor for one of these classes. There is a better (and more cryptic)
way to achieve the same objective without the need to pass the reference.
Again, since this program was designed for clarity, we are doing it the
obvious way. Another program later in the lesson shows the preferred way.
WProc1 winProcCmd1 = new WProc1(displayWindow); WProc2 winProcCmd2 = new WProc2(); |
Pay close attention to the syntax of these two statements, because you
will be using this syntax often. In subsequent lessons, we will dig deeper
into the Delegation Event Model and teach you what is going on behind
the scenes when you execute statements of this sort.
displayWindow.addWindowListener(winProcCmd1); displayWindow.addWindowListener(winProcCmd2); |
These listener objects are notified by invoking the methods in the objects which match the specific type of the event (open window, close window, closing window, minimize window, etc.).
We wrap up the definition of our GUI class with a statement which
causes the Frame object to become visible on the screen. Note that
this statement also causes the windowActivated and windowOpened
events to be generated.
displayWindow.setVisible(true); }//end constructor }//end GUI class definition |
The code fragments that follow describe the two classes that can be used to instantiate Listener objects.
The first class definition that we will look at implements the WindowListener interface. This requires that all the methods declared in the interface be defined in this class. This class defines all of the methods. Each of the methods displays a descriptive message whenever it is invoked.
We will begin our discussion with the constructor. Note that the constructor
for this class requires a reference to the Source object
to be passed as a parameter. As mentioned earlier, this is not the preferred
way to accomplish our objective, but it is the most straightforward and
easy to understand. That is why we elected to use it here. The code in
the constructor saves a reference to the Source object in an instance
variable named displayWindowRef.
class WProc1 implements WindowListener{ Frame displayWindowRef; WProc1(Frame windowIn){//constructor this.displayWindowRef = windowIn; }//end constructor |
If you examine the complete program listing that is presented later, you will see that there is one method definition in this class definition for each of the methods that are declared in the WindowListener interface.
The definition of all the interface methods are very similar, so I am not going to show them all here. I will show the one that requires the reference to the source object that was discussed above.
This is our definition of the windowClosing() event handler method. As you can see, this method starts out by displaying a message. However, it then invokes the dispose() method on the Frame object, and that is the reason that a reference to the Frame object was required to be passed in as a parameter.
Invoking the dispose() method causes a WindowClosed event
to be generated.
public void windowClosing(WindowEvent e){ System.out.println("WProc1 windowClosing test msg"); displayWindowRef.dispose();//generate WindowClosed }//end windowClosing() |
In this case, only two of the methods of the WindowListener
interface are overridden. These overridden methods display a message
whenever they are invoked.
class WProc2 extends WindowAdapter{ public void windowIconified(WindowEvent e){ System.out.println( "******** WProc2 windowIconified test msg"); }//end windowIconified() public void windowDeiconified(WindowEvent e){ System.out.println( "******** WProc2 windowDeiconified test msg"); }//end windowDeiconified() }//end class WProc2 |
This program was tested using JDK 1.1.3 under Win95. When executed, this application places a simple empty Frame object on the screen. Starting the program produces the following output: WProc1 windowActivated test msg Wproc1 windowOpened test msg Pressing the minimize button on the Frame produces the following output: WProc1 windowIconified test msg ******** WProc2 windowIconified test msg WProc1 windowDeactivated test msg Restoring the Frame after minimization produces the following output: WProc1 windowActivated test msg WProc1 windowDeiconified test msg ******** WProc2 windowDeiconified test msg WProc1 windowActivated test msg Closing the Frame by pressing the X-icon in the upper right of the Frame produces the following output. WProc1 windowClosing test msg WProc1 windowDeactivated test msg WProc1 windowClosed test msg |
Note that as discussed earlier, an improved version of this program is presented at the end of this lesson. The improved version does not require the passing of a Frame object reference to the constructor for the WindowListener object in order to make it possible for the WindowListener object to reference the Frame object. You should become familiar with the methodology used in the improved version as well as the methodology used in this following version.
/*File Event08.java Copyright 1997, R.G.Baldwin Rev 01/10/98 Illustrates the use of Event Sources, Event Listeners, and Adapters in the Delegation Event Model. Briefly, this application instantiates an object which creates a user interface consisting of a simple Frame object. This object is an Event Source which notifies two different Event Listener objects of Window events. One of the Listener objects implements the WindowListener interface and overrides all of the methods declared in that interface. The other Listener object extends the Adapter class named WindowAdapter. The purpose of Adapter classes is to implement the Listener interfaces and to define all of the methods with empty methods. Classes which extend the Adapter classes can then selectively override only those methods of interest. This Listener object overrides only two of the methods. Note that this application does not terminate and return control to the operating system. You must forcefully terminate it. This program was tested using JDK 1.1.3 under Win95. When executed, this application places a simple empty Frame object on the screen. Starting the program produces the following output: WProc1 windowActivated test msg Wproc1 windowOpened test msg Pressing the minimize button on the Frame produces the following output: WProc1 windowIconified test msg ******** WProc2 windowIconified test msg WProc1 windowDeactivated test msg Restoring the Frame after minimization produces the following output: WProc1 windowActivated test msg WProc1 windowDeiconified test msg ******** WProc2 windowDeiconified test msg WProc1 windowActivated test msg Closing the Frame by pressing the X-icon in the upper right of the Frame produces the following output. WProc1 windowClosing test msg WProc1 windowDeactivated test msg WProc1 windowClosed test msg **********************************************************/ import java.awt.*; import java.awt.event.*; public class Event08 { public static void main(String[] args){ GUI gui = new GUI();//instantiate a GUInterface object }//end main }//end class Event08 //=======================================================// //The following class is used to instantiate a user // interface object, to instantiate two Listener objects, // and to register those two objects for notification // whenever a Window event occurs. class GUI{ public GUI(){//constructor //Create a new Frame object Frame displayWindow = new Frame(); displayWindow.setSize(300,200); displayWindow.setTitle("Copyright 1997, R.G.Baldwin"); //Instantiate two Listener objects which will process // Window events WProc1 winProcCmd1 = new WProc1(displayWindow); WProc2 winProcCmd2 = new WProc2(); //Register the Listener objects for notification of // Window events. This object is the Event Source. displayWindow.addWindowListener(winProcCmd1); displayWindow.addWindowListener(winProcCmd2); //windowActivated and windowOpened test messages // are produced here displayWindow.setVisible(true); }//end constructor }//end class GUI definition //=======================================================// //The following two classes can be used to instantiate // Listener objects. Note that this class implements the // WindowListener interface. This requires that all the // methods declared in the interface be overridden in this // class. This class overrides all of the methods and // displays a descriptive message whenever one of the // methods is invoked. class WProc1 implements WindowListener{ //used to save a reference to the Frame object Frame displayWindowRef; WProc1(Frame windowIn){//constructor // save ref to Frame object this.displayWindowRef = windowIn; }//end constructor public void windowClosed(WindowEvent e){ System.out.println("WProc1 windowClosed test msg"); }//end windowClosed() public void windowIconified(WindowEvent e){ System.out.println("WProc1 windowIconified test msg"); }//end windowIconified() public void windowOpened(WindowEvent e){ System.out.println("WProc1 windowOpened test msg"); }//end windowOpened() public void windowClosing(WindowEvent e){ System.out.println("WProc1 windowClosing test msg"); displayWindowRef.dispose();//generate WindowClosed }//end windowClosing() public void windowDeiconified(WindowEvent e){ System.out.println( "WProc1 windowDeiconified test msg"); }//end windowDeiconified() public void windowActivated(WindowEvent e){ System.out.println("WProc1 windowActivated test msg"); }//end windowActivated() public void windowDeactivated(WindowEvent e){ System.out.println( "WProc1 windowDeactivated test msg"); }//end windowDeactivated() }//end class WProc1 //=======================================================// //This and the previous class can be used to instantiate // Listener objects. Note that this class extends an // Adapter class which can be used to avoid the // requirement to define all of the methods of the // actual Listener class named WindowListener. This class // overrides only two of the methods declared in the // interface. It displays a message whenever one of the // methods is invoked. class WProc2 extends WindowAdapter{ public void windowIconified(WindowEvent e){ System.out.println( "******** WProc2 windowIconified test msg"); }//end windowIconified() public void windowDeiconified(WindowEvent e){ System.out.println( "******** WProc2 windowDeiconified test msg"); }//end windowDeiconified() }//end class WProc2 |
The propagation of an event from a Source object to a Listener object involves invoking a method on the Listener object and passing an object which contains encapsulated information about the event. Note that each event class may include more than one actual type of event.
A Listener object is an instance of a class that implements a specific EventListener interface extended from the generic java.util.EventListener.
An EventListener interface declares one or more methods which must be defined in the Listener class, and which are invoked by the event source in response to each specific event type handled by the interface.
The invoking of these methods is the mechanism by which the Source notifies the Listener of the occurrence of an event of a specific type.
An Event Source is an object which "originates" or "fires" events by invoking the methods of one or more Listener objects. The Source maintains a list containing a reference to all of the Listener objects that have registered to be notified of events of that class.
The programmer causes Listener objects to be added to this list using add<EventType>Listener method calls.
Placing references to Listener objects on the list is often referred to as registering specific Listeners to receive notification of specific events.
Once the list is populated (Listener objects are registered), the Source object uses that list to notify each Listener of the occurrence of an event of the specified type without further effort on the part of the programmer.
The Event Source is often a GUI component and the Listener is commonly an object of a class which implements the appropriate listener interface, but this is not a requirement. For example we will learn later how to cause a program to generate events without any physical involvement on the part of a user and a GUI component.
The Listener object could also be another AWT component which implements one or more Listener interfaces for the purpose of hooking GUI objects up to each other.
Since a single event class may be used to represent more than one event type (i.e. MouseEvent represents mouse up, mouse down, mouse drag, mouse move, etc), some event classes may also contain an "id" (unique within that class) which maps to its specific event types.
There are no public fields in the new event classes. Rather the data in the event is encapsulated and available only through the use of appropriate set...() and get...() methods.
The set methods only exist for attributes on an event that can be modified by a listener. If you continue with your studies in Java, you will learn that the set and get methods match a design pattern for Java Beans.
A concrete set of event classes is defined by the AWT. In addition, programmers may define their own event types by subclassing either java.util.EventObject or one of the AWT event classes.
|
|
Semantic events are defined at a higher-level to encapsulate
the semantics of a user interface component's model. As of February 1997,
the semantic event classes defined by the JDK 1.1 version of the AWT were
as follows:
|
Even though the above discussion seems to tie these event classes to user actions on screen components (because that is the norm), you need to remember that there is nothing to prevent you from having your code generate events of these types completely independent of such user actions. For example, you can easily cause an ActionEvent to be generated and attributed to some component whenever a software timer expires. We will learn how to do this sort of thing in subsequent lessons.
As of February 1997, the low-level listener interfaces defined by the
JDK 1.1 version of the AWT were as follows:
|
The semantic listener interfaces defined by the AWT are as follows:
|
According to JDK 1.1 documentation,
"The API makes no guarantees about the order in which the events are delivered to a set of registered listeners for a given event on a given source. Additionally, any event which allows its properties to be modified (via setXXX() methods) will be explicitly copied such that each listener receives a replica of the original event. If the order in which events are delivered to listeners is a factor for your program, you should chain the listeners off a single listener which is registered on the source (the fact that the event data is encapsulated in a single object makes propagating the event extremely simple)." |
As before, a distinction is drawn between low-level and semantic events. The source for low-level events will normally be one of the visual component classes (Button, Scrollbar, etc.) because the event is bound to the actual component on the screen (but counterfeit events can be generated).
As of February 1997, JDK 1.1 defined low-level listeners on the following
components.
|
As of February 1997, JDK 1.1 defined the following semantic listeners
for AWT components:
|
A single ActionEvent listener object could be registered to be notified of action events on one or more components of all of these types. Of course, it would then be necessary for the code in that event handler to determine which source was responsible for generating the event.
An important difference between low level events and semantic events has to do with where the classes that define those events plug into the class hierarchy. Low level events plug in further down the class hierarchy and inherit more methods that can be used to process the event object than is the case with semantic events.
When you implement an interface, you are required to define all of the methods that are declared in the interface, even if you define them with empty methods. In some cases, the requirement to define all the methods declared in an interface can be burdensome.
For this reason (and possibly for some other reasons as well), the AWT provides a set of abstract adapter classes which match up with the defined interfaces. Each adapter class implements one interface and defines all of the methods declared by that interface as empty methods, thus satisfying the requirement to define all of the methods.
You can then define your listener classes by extending the adapter classes instead of implementing the listener interfaces.. This allows you the freedom to override only those methods of the interface which interest you.
Again, recall that the methods declared within an interface correspond to the individual event types contained within a corresponding event class, and the Source object notifies your Listener object of the occurrence of an event of a specific type by invoking your interface method.
As of February 1997, the Adapter classes provided by the JDK 1.1 version
of the AWT were as follows:
|
This filtering of events should improve performance, especially with high frequency events, such as mouse-moves.
According to the JDK 1.1 documentation,
|
The previous program implemented an Event Source object which notified two different Listener objects of the occurrence of an event in the Window class.
The following program implements an Event Source object which notifies one Listener object of the occurrence of an event in the Window class and notifies another Listener object of the occurrence of an event in the Mouse class.
As mentioned earlier, this program implements a MouseListener interface on a Frame object, which is possible because the Frame class indirectly extends the Component class, and addMouseListener() is defined on the Component class.
If you compile and execute this program, whenever you click the mouse inside the Frame, you should see the coordinates of the mouse pointer displayed above the mouse pointer.
public class Event09 { public static void main(String[] args){ GUI gui = new GUI();//instantiate a GUI }//end main }//end class Event09 |
In this program, we are going to override the paint() method to make it possible for us to draw coordinate information on the screen. We also discussed drawing on the screen in the lesson on Applets, so you might need to refer back to that also. (We will have a lot more to say about drawing on the screen when we get into graphics later.)
In order to override the paint() method, we need to extend the
Frame class to produce our own version of the Frame class
where we have the ability to override the paint() method. The following
code fragment extends Frame into MyFrame and overrides
the paint() method.
class MyFrame extends Frame{ int clickX; int clickY; public void paint(Graphics g){ g.drawString( "" + clickX + ", " + clickY, clickX, clickY); }//end paint() }//end class MyFrame |
The overridden version of the paint() method causes the coordinate values stored in clickX and clickY to be displayed in the client area of the Frame object at the location specified by the values of those two instance variables.
If you review the particulars of the drawString() method, you will see that it needs three parameters. The first parameter is the string to draw on the screen. The next two parameters are the coordinate values in pixels where the string is to be drawn.
As is normally the case, coordinate values are specified relative to the upper left-hand corner of the object being drawn on. The above overridden version of the drawString() method converts the coordinate values to a string, and draws that string at the location specified by the coordinate values.
As before, the GUI class is rather long. Therefore, we will break it up and discuss it in sections.
The first fragment that we will discuss is the constructor. The important thing to note here is that we are not instantiating an object of type Frame. Rather, we are instantiating an object of type MyFrame which is our extended version of Frame.
Other than that, this is pretty standard stuff by now.
class GUI { public GUI(){//constructor //Create a new Frame object, set size, title, etc. MyFrame displayWindow = new MyFrame(); displayWindow.setSize(300,300); displayWindow.setTitle("Copyright 1997, R.G.Baldwin"); displayWindow.setVisible(true); |
The second is a MouseListener object that will process mouse events on the MyFrame object.
It is typical to register listener objects as anonymous objects in those
cases where a specific reference to the listener object is not otherwise
needed.
displayWindow.addWindowListener(new WProc1()); displayWindow.addMouseListener( new MouseProc(displayWindow)); }//end constructor }//end class GUI definition |
We will begin with the MouseListener class. Note that this class extends the MouseAdapter class and does not directly implement the MouseListener interface. This saves us the trouble of having to create empty methods for event types that we are not interested in.
Objects of this class that are registered on the Source will be notified whenever a mousePressed() event occurs on the Source. This will cause the mousePressed() method to be invoked which will display the coordinates of the mouse pointer when the mouse is pressed on the source object. Note that this class extends an adapter class.
When the mousePressed() method is invoked, it receives an object of type MouseEvent as a parameter. Different types of events encapsulate different types of information in the object that is passed as a parameter. This particular object contains a variety of information, including the coordinates of the mouse pointer when the event occurred.
The code in the overridden mousePressed() method extracts that coordinate information from the object and stores it in the instance variables named clickX and clickY of the Source object.
Then it invokes the repaint() method on the source object, causing
the source object to be repainted on the screen. This causes the overridden
paint() method discussed earlier to be invoked, which displays the
new coordinate information on the screen in the proper location.
class MouseProc extends MouseAdapter{ MyFrame refToWin; //save a reference to the source here MouseProc(MyFrame inWin){//constructor refToWin = inWin;//save ref to window }//end constructor public void mousePressed(MouseEvent e){ refToWin.clickX = e.getX(); refToWin.clickY = e.getY(); refToWin.repaint(); }//end mousePressed() }//end class MouseProc |
class WProc1 extends WindowAdapter{ public void windowClosing(WindowEvent e){ System.exit(0); }//end windowClosing() }//end class WProc1 |
/*File Event09.java Copyright 1997, R.G.Baldwin This program is designed to be compiled under JDK 1.1 Illustrates the use of Event Sources, Event Listeners, and Adapters in the Delegation Event Model. This program instantiates a Listener object to process mouse events. When a mouse press occurs in a Frame object, the program gets the coordinates and then displays those coordinates near the point of the mouse press. This program was tested using JDK 1.1.3 under Win95. **********************************************************/ import java.awt.*; import java.awt.event.*; public class Event09 { public static void main(String[] args){ GUI gui = new GUI();//instantiate a GUI }//end main }//end class Event09 //=======================================================// //Subclass Frame in order to override the paint method. class MyFrame extends Frame{ int clickX; int clickY; public void paint(Graphics g){ g.drawString( "" + clickX + ", " + clickY, clickX, clickY); }//end paint() }//end class MyFrame //=======================================================// //The following class is used to instantiate a // graphical user interface object. class GUI { public GUI(){//constructor //Create a new Frame object, set size, title, etc. MyFrame displayWindow = new MyFrame(); displayWindow.setSize(300,300); displayWindow.setTitle("Copyright 1997, R.G.Baldwin"); displayWindow.setVisible(true); //Instantiate and register an anonymous Listener // object which will terminate the program when the // user closes the Frame. displayWindow.addWindowListener(new WProc1()); //Instantiate and register an anonymous Listener // object that will process mouse events to determine // and display the coordinates when the user presses // the mouse button in the client area of the Frame. displayWindow.addMouseListener( new MouseProc(displayWindow)); }//end constructor }//end class GUI definition //=======================================================// //This listener class monitors for mouse presses and // displays the coordinates of the mouse pointer when the // mouse is pressed on the source object. Note that this // class extends is an adapter class. class MouseProc extends MouseAdapter{ MyFrame refToWin; //save a reference to the source here MouseProc(MyFrame inWin){//constructor refToWin = inWin;//save ref to window }//end constructor //Override the mousePressed method to determine and // display the coordinates when the mouse is pressed. public void mousePressed(MouseEvent e){ //Get X and Y coordinates of mouse pointer and store // in an instance variable of the Frame object refToWin.clickX = e.getX(); refToWin.clickY = e.getY(); //Force the Frame object to be repainted in order to // display the coordinate information. refToWin.repaint(); }//end mousePressed() }//end class MouseProc //=======================================================// //The following listener is used to terminate the program // when the user closes the frame. Note that this class // extends an adapter class. class WProc1 extends WindowAdapter{ public void windowClosing(WindowEvent e){ System.exit(0); }//end windowClosing() }//end class WProc1 //=======================================================// |
In the simplest case, you can handle low-level events in JDK 1.1 with the following steps. (Semantic events will be discussed in a subsequent lesson).
If you implement the listener interface, you must define all interface methods. If instead you extend the corresponding adapter class, you can override only those methods which tie to event types of interest.
displayWindow.addMouseListener(mouseProcCmd); |
The notification takes the form of invoking a method in the mouseProcCmd object where there must be a corresponding method for each specific event type in the class of mouse events (but some of those methods can be empty shells if you have no interest in some of the event types).
Another sample program required the Source object to notify two different Listener objects of the occurrence of events of two different classes on a single screen object.
It is also possible to cause a single Listener object to be registered to receive notification of the occurrence of events of a given class on more than one source object. In that case, it is normally necessary for the code in the Listener object to crack open the event object to determine which screen object was responsible for the event (if it matters).
Also, the JDK 1.1 documentation indicates that it is possible to have event-style communication between objects that are not screen objects. Subsequent lessons will investigate a number of these possibilities.
Make your name appear in the banner at the top of the object.
Implement the WindowListener interface to cause an appropriate message to appear on the screen whenever you perform any of the actions associated with the methods declared in that interface.
Make certain that your application terminates and returns control to the operating system when the user clicks on the "close" button in the upper right-hand corner of the object.
Performing various operations on the object should produce screen outputs
similar to the following:
WindowProcessor windowIconified test msg WindowProcessor windowDeactivated test msg WindowProcessor windowActivated test msg WindowProcessor windowDeiconified test msg WindowProcessor windowActivated test msg WindowProcessor windowClosing test msg |
/*File SampProg117.java from lesson 80 Copyright 1997, R.G.Baldwin */ import java.awt.*; import java.awt.event.*; public class SampProg117 { public static void main(String[] args){ //instantiate a Graphical User Interface object GUI gui = new GUI(); }//end main }//end class SampProg117 //--------------------------------------------------------- class GUI{ public GUI(){//constructor //create a new Frame object Frame displayWindow = new Frame(); displayWindow.setSize(300,100); displayWindow.setTitle("Copyright 1997, R.G.Baldwin"); displayWindow.setVisible(true); //Instantiate and Register a Listener object for // notification of Window events. displayWindow.addWindowListener( new WindowProcessor(displayWindow)); }//end constructor }//end class GUI definition //---------------------------------------------------------- class WindowProcessor implements WindowListener{ Frame displayWindowRef; WindowProcessor(Frame windowIn){//constructor //save ref to the Frame object passed as a parameter this.displayWindowRef = windowIn; }//end constructor public void windowClosed(WindowEvent e){ System.out.println( "WindowProcessor windowClosed test msg"); }//end windowClosed() public void windowIconified(WindowEvent e){ System.out.println( "WindowProcessor windowIconified test msg"); }//end windowIconified() public void windowOpened(WindowEvent e){ System.out.println( "WindowProcessor windowOpened test msg"); }//end windowOpened() public void windowClosing(WindowEvent e){ System.out.println( "WindowProcessor windowClosing test msg"); displayWindowRef.setVisible(false); //hide the window System.exit(0); }//end windowClosing() public void windowDeiconified(WindowEvent e){ System.out.println( "WindowProcessor windowDeiconified test msg"); }//end windowDeiconified() public void windowActivated(WindowEvent e){ System.out.println( "WindowProcessor windowActivated test msg"); }//end windowActivated() public void windowDeactivated(WindowEvent e){ System.out.println( "WindowProcessor windowDeactivated test msg"); }//end windowDeactivated() }//end class WindowProcessor |
Make your name appear in the banner at the top of the object.
Make certain that your application terminates and returns control to the operating system when the user clicks on the "close" button in the upper right-hand corner of the object.
Extend the WindowAdapter class to cause the three messages shown below
to appear on the screen when the object is minimized, restored, and closed.
WindowProcessor windowIconified test msg WindowProcessor windowDeiconified test msg WindowProcessor windowClosing test msg |
/*File SampProg118.java from lesson 80 Copyright 1997, R.G.Baldwin */ import java.awt.*; import java.awt.event.*; public class SampProg118 { public static void main(String[] args){ //instantiate a Graphical User Interface object GUI gui = new GUI(); }//end main }//end class SampProg118 //--------------------------------------------------------- class GUI{ public GUI(){//constructor //create a new Frame object Frame displayWindow = new Frame(); displayWindow.setSize(300,100); displayWindow.setTitle("Copyright 1997, R.G.Baldwin"); displayWindow.setVisible(true); //Instantiate and Register a Listener object for // notification of Window events. displayWindow.addWindowListener( new WindowProcessor()); }//end constructor }//end class GUI definition //---------------------------------------------------------- class WindowProcessor extends WindowAdapter{ public void windowIconified(WindowEvent e){ System.out.println( "WindowProcessor windowIconified test msg"); }//end windowIconified() public void windowClosing(WindowEvent e){ System.out.println( "WindowProcessor windowClosing test msg"); System.exit(0); }//end windowClosing() public void windowDeiconified(WindowEvent e){ System.out.println( "WindowProcessor windowDeiconified test msg"); }//end windowDeiconified() }//end class WindowProcessor |
Make your name appear in the banner at the top of the object.
Make certain that your application terminates and returns control to the operating system when the user clicks on the "close" button in the upper right-hand corner of the object.
Implement a Listener interface to cause the application to terminate when the user presses the close button.
Extend an adapter class to process mouse events. When a mouse press occurs in the Frame object, the program displays the mouse coordinates near the point of the mouse press.
A - See program below.
/*File SampProg119.java from lesson 80 Copyright 1997, R.G.Baldwin */ import java.awt.*; import java.awt.event.*; public class SampProg119 { public static void main(String[] args){ //instantiate a Graphical User Interface object GUI gui = new GUI(); }//end main }//end class SampProg119 //--------------------------------------------------------- //Subclass Frame in order to override the paint method. class MyFrame extends Frame{ int clickX; int clickY; public void paint(Graphics g){ g.drawString( "" + clickX + ", " + clickY, clickX, clickY); }//end paint() }//end class MyFrame //--------------------------------------------------------- class GUI { public GUI(){//constructor //create a new Frame object MyFrame displayWindow = new MyFrame(); displayWindow.setSize(300,300); displayWindow.setTitle("Copyright 1997, R.G.Baldwin"); displayWindow.setVisible(true); //Instantiate and register a Listener object that will // terminate the program when the user closes the // window. displayWindow.addWindowListener(new WProc1()); //Instantiate and register a Listener object that will // process mouse events to determine and display the // coordinates when the user presses the mouse button. displayWindow.addMouseListener( new MProc1(displayWindow)); }//end constructor }//end class GUI definition //--------------------------------------------------------- //This listener class monitors for mouse presses and // displays the coordinates of the mouse pointer when the // mouse is pressed. class MProc1 extends MouseAdapter{ MyFrame refToWin; //save a reference to the window here MProc1(MyFrame inWin){//constructor refToWin = inWin;//save ref to window }//end constructor //Override the mousePressed method to determine and // display the coordinates when the mouse is pressed. public void mousePressed(MouseEvent e){ //Get X and Y coordinates of mouse pointer // and store in the Frame object. refToWin.clickX = e.getX(); refToWin.clickY = e.getY(); refToWin.repaint();//display coordinate information }//end mousePressed() }//end class MProc1 //--------------------------------------------------------- class WProc1 implements WindowListener{ public void windowClosed(WindowEvent e){} public void windowIconified(WindowEvent e){} public void windowOpened(WindowEvent e){} public void windowClosing(WindowEvent e){ System.exit(0); }//end windowClosing() public void windowDeiconified(WindowEvent e){} public void windowActivated(WindowEvent e){} public void windowDeactivated(WindowEvent e){} }//end class Wproc1 |
A - See program below.
/*File Event08A.java Copyright 1997, R.G.Baldwin Modify the program named Event08 to eliminate the requirement to pass a reference to the Frame object to the constructor of the Window listener in order to make the Frame become invisible. This program is designed to be compiled under JDK 1.1 Illustrates the use of Event Sources, Event Listeners, and Adapters in the Delegation Event Model. Briefly, this application instantiates an object which creates a user interface consisting of a simple Frame object. This object is an Event Source which notifies two different Event Listener objects of Window events. One of the Listener objects implements the WindowListener interface and overrides all of the methods declared in that interface. The other Listener object extends the Adapter class named WindowAdapter. The purpose of the Adapter classes is to implement the basic Listener interfaces and override all of the methods with empty methods. Classes which extend the Adapter classes can then selectively override only those methods of interest. This Listener object overrides only two of the methods. This application illustrates the requirement to replace the resize() method from JDK 1.0.2 with the setSize() method from JDK 1.1, and to replace the show() method from JDK 1.0.2 with the setVisible() method from JDK 1.1. Note that there are many other methods which must be similarly replaced when converting JDK 1.0.2 applications to JDK 1.1 applications but these are the only two which occurred in this application. Note that this application does not terminate. You must forcefully terminate it. When executed, this application places a simple empty Frame object on the screen. Pressing the minimize button on the Frame produces the following output: WProc1 windowIconified test msg ******** WProc2 windowIconified test msg WProc1 windowDeactivated test msg Restoring the Frame after minimization produces the following output: WProc1 windowActivated test msg WProc1 windowDeiconified test msg ******** WProc2 windowDeiconified test msg WProc1 windowActivated test msg (This dup is not a typo) Closing the Frame by pressing the X-icon in the upper right of the Frame produces the following output and causes the Frame to become invisible. WProc1 windowClosing test msg WProc1 windowDeactivated test msg Note that none of these activities invoked the WindowClosed() or WindowOpened() methods. These results were produced using JDK 1.1.3 running under Windows 95. */ //=======================================================// import java.awt.*; import java.awt.event.*; public class Event08A { public static void main(String[] args){ //instantiate a Graphical User Interface object GUI gui = new GUI(); }//end main }//end class Event08A //The following class is used to instantiate a user // interface object, to instantiate two Listener objects, // and to register those two objects for notification // whenever a Window event occurs. class GUI{ public GUI(){//constructor //create a new Frame object Frame displayWindow = new Frame(); displayWindow.setSize(300,200); displayWindow.setTitle("Copyright 1997, R.G.Baldwin"); displayWindow.setVisible(true); //Instantiate and register the Listener objects for // notification of Window events. Note that anonymous // instantiation of the Listener objects is used and // no reference to the Frame object is passed to the // constructor for the Listener objects. displayWindow.addWindowListener(new WProc1()); displayWindow.addWindowListener(new WProc2()); }//end constructor }//end class GUI definition //The following two classes can be used to instantiate // Listener objects. Note that this class implements the // WindowListener interface. This requires that all the // methods declared in the interface be overridden in this // class. This class overrides all of the methods and // displays a descriptive message whenever one of the // methods is invoked. class WProc1 implements WindowListener{ public void windowClosed(WindowEvent e){ System.out.println("WProc1 windowClosed test msg"); }//end windowClosed() public void windowIconified(WindowEvent e){ System.out.println("WProc1 windowIconified test msg"); }//end windowIconified() public void windowOpened(WindowEvent e){ System.out.println("WProc1 windowOpened test msg"); }//end windowOpened() public void windowClosing(WindowEvent e){ System.out.println("WProc1 windowClosing test msg"); //Note the following use of the incoming object to // access the Frame object. e.getComponent().setVisible(false); }//end windowClosing() public void windowDeiconified(WindowEvent e){ System.out.println( "WProc1 windowDeiconified test msg"); }//end windowDeiconified() public void windowActivated(WindowEvent e){ System.out.println("WProc1 windowActivated test msg"); }//end windowActivated() public void windowDeactivated(WindowEvent e){ System.out.println( "WProc1 windowDeactivated test msg"); }//end windowDeactivated() }//end class WProc1 //This and the previous class can be used to instantiate // Listener objects. Note that this class extends an Adapter // class which can be used to avoid the requirement to // override all of the methods of the actual Listener class // named WindowListener. The Adapter named WindowAdapter // implements WindowListener and overrides all of the // required methods with empty methods which can be // selectively overridden. This class overrides only two of // the methods declared in the interface. It displays a // message whenever one of the methods is invoked. class WProc2 extends WindowAdapter{ public void windowIconified(WindowEvent e){ System.out.println( "******** WProc2 windowIconified test msg"); }//end windowIconified() public void windowDeiconified(WindowEvent e){ System.out.println( "******** WProc2 windowDeiconified test msg"); }//end windowDeiconified() }//end class WProc2 //=======================================================// |
A - See program below.
/*File Event09A.java Copyright 1997, R.G.Baldwin Rewrite the program named Event09 to eliminate the requirement to pass a reference to the MyFrame object to the constructor for the Mouse Listener object. This program is designed to be compiled under JDK 1.1 Illustrates the use of Event Sources, Event Listeners, and Adapters in the Delegation Event Model. This program instantiates a Listener object to process mouse events. When a mouse press occurs in a Frame object, the program gets the coordinates and then displays those coordinates near the point of the mouse press. These results were produced using JDK 1.1.3, running under Windows 95. */ //=======================================================// import java.awt.*; import java.awt.event.*; public class Event09A { public static void main(String[] args){ //instantiate a Graphical User Interface object GUI gui = new GUI(); }//end main }//end class Event09A //=======================================================// //Subclass Frame in order to override the paint method. class MyFrame extends Frame{ int clickX; int clickY; public void paint(Graphics g){ g.drawString( "" + clickX + ", " + clickY, clickX, clickY); }//end paint() }//end class MyFrame //=======================================================// //The following class is used to instantiate a graphical // user interface object. class GUI { public GUI(){//constructor //create a new Frame object MyFrame displayWindow = new MyFrame(); displayWindow.setSize(300,300); displayWindow.setTitle("Copyright 1997, R.G.Baldwin"); displayWindow.setVisible(true); //Instantiate and register Listener object which will // terminate the program when the user closes the // Frame. WProc1 winProcCmd1 = new WProc1(); displayWindow.addWindowListener(winProcCmd1); //Instantiate and register Listener object which will // process mouse events to determine and display the // coordinates when the user presses the mouse button. // Note that the Listener object is instantiated // anonymously and no reference to the MyFrame object // is passed to the constructor for the Listener // object. displayWindow.addMouseListener(new MouseProc()); }//end constructor }//end class GUI definition //=======================================================// //This listener class monitors for mouse presses and // displays the coordinates of the mouse pointer when the // mouse is pressed. class MouseProc extends MouseAdapter{ //Override the mousePressed method to determine and // display the coordinates when the mouse is pressed. public void mousePressed(MouseEvent e){ //Get x and y coordinates of the mouse pointer and // store in the instance variables of the MyFrame // object. Note the requirement to cast the component // to the type of MyFrame in order to access the // instance variables. ((MyFrame)e.getComponent()).clickX = e.getX(); ((MyFrame)e.getComponent()).clickY = e.getY(); //display coordinate information e.getComponent().repaint(); }//end mousePressed() }//end class MouseProc //=======================================================// //The following listener is used to terminate the program // when the user closes the frame. class WProc1 extends WindowAdapter{ public void windowClosing(WindowEvent e){ System.exit(0); }//end windowClosing() }//end class WProc1 //=======================================================// |
A - See example programs above named Event08A and Event09A for clues as to how to accomplish this requirement.
-end-