JDK 1.1 was released on February 18, 1997 and JDK 1.1.1 was released on March 27, 1997. This lesson was originally written on March 30, 1997 using the software and documentation in the JDK 1.1.1 download package.
One of my teaching objectives is to present every concept in the simplest possible terms, devoid of confusing extraneous material. This lesson contains about the simplest example program that I was able to write that illustrates the posting of events.
In this lesson, a Label object impersonates a Button object by posting counterfeit ActionEvent objects attributable to the Button. The events are picked up by the system and processed just as though they were actually generated by the Button. In particular, they are delivered to an ActionListener object registered on the Button object where they are processed just as though they originated at the Button object.
This sample program operates completely within the Source/Listener concept of the Delegation Event Model.
Unlike a previous sample program, this program does not override any of the processXxxxEvent() methods. Rather, this program works completely within the Source/Listener concept of the Delegation Event Model.
Two Label objects and a Button object are instantiated and added to a Frame object. When the Button object is clicked, an ActionEvent is generated and trapped by an ActionListener object registered on the Button object. Code in the actionPerformed() method of the ActionListener object toggles the background color of one of the Label objects back and forth between yellow and blue.
Up to this point, everything is pretty normal. However, a MouseListener object is registered on the other Label. When that Label object is clicked, code in the mouseClicked() method of the MouseListener object generates a counterfeit ActionEvent object and posts it to the SystemEventQueue.
The code in the Label's MouseListener object impersonates the Button object by placing the identification of the Button object into the "source" field of the counterfeit ActionEvent object.
The runtime system delivers the counterfeit ActionEvent object to the ActionListener object registered on the Button object. The final result is that clicking on the Label object invokes the actionPerformed() method registered on the Button object, so clicking on the Label object has exactly the same result as clicking on the Button object.
The program was tested using JDK 1.1.1 and Win95. An interesting sidelight is that the counterfeit button constructed from the Label object is much more responsive than the real button. In other words, the counterfeit button can service mouse clicks at a much more rapid rate than the real button.
This probably has something to do with the requirement to redraw the button twice each time it is clicked in order to animate it. An interesting exercise for the student would be to respond to the pressed and released events of the mouse on the Label to change the background color of the Label while it is pressed to see if that would produce a similar degradation of the responsiveness of the counterfeit button.
The first interesting code fragment is the pair of statements in the constructor which register Listener objects on the Label and the Button. An important point to note is that a reference to the Button object is passed to the constructor of the MouseListener object for the Label. It is through this link that the Label is able to create a counterfeit ActionEvent object and attribute it to the Button.
It is also interesting to note that the Listener object for the
Label knows nothing about the other Label object whose color
is changed during the operation of the program. This is because the Label
object that impersonates the Button does not directly change
the color of the other Label object. Rather, by impersonating the
Button object, it causes the ActionListener object on the
Button to perform that task. In fact, it has no knowledge of the
outcome of its impersonation. All it knows is that it posts an ActionEvent
object and attributes it to the Button.
clickMeLabel.addMouseListener( new MyMouseListener(clickMeButton)); clickMeButton.addActionListener( new MyActionListener(colorMeLabel)); |
In this case, that reference is passed as a parameter when the MouseListener object is constructed but there are probably other ways to accomplish this as well. For example, code might be able to "peek" into the SystemEventQueue in hopes of copying an ActionEvent object and obtaining a reference to the Button. That is why special security provisions apply to the SystemEventQueue for Applets.
Because the counterfeit ActionEvent object is attributed
to the Button object, it is delivered to the ActionListener object
for the Button where it is processed just as though it actually
originated at the Button.
//Note that the following is a single statement Toolkit.getDefaultToolkit(). getSystemEventQueue(). postEvent(new ActionEvent(clickMeButton, ActionEvent. ACTION_PERFORMED, "counterfeit")); |
public ActionEvent(Object source, int id, String command)
specified source object. originated command - the command string for this action event |
As mentioned in an earlier lesson, it is very important that you specify a correct id parameter. Otherwise, the ActionEvent object won't be delivered by the runtime system.
I promised you earlier that this was going to be a simple program. The remaining code is standard code that you have seen many times before so we won't highlight it as being interesting. A complete listing of the program is presented in the next section.
/*File Event31.java Copyright 1997, R.G.Baldwin Reformatted 10/5/97 to fit better on the screen. This program was designed to be compiled and executed under JDK 1.1.1. This program demonstrates the use of the postEvent() method to post ActionEvents to the SystemEventQueue. In this program, a Label object impersonates a Button object by posting counterfeit ActionEvent objects and attributes them to the Button object. Unlike a previous sample program, this program does not override any of the processXxxxEvent() methods. Rather, this program works completely within the Source/Listener concept of the Delegation Event Model. Two Labels and a Button are instantiated and added to a Frame object. When the Button object is clicked, an ActionEvent is generated and trapped by an ActionListener object registered on the Button object. Code in the actionPerformed() method of the Listener object toggles the background color of one of the Label objects back and forth between yellow and blue. So far, everything is pretty standard. However, a MouseListener object is registered on the other Label. When that Label object is clicked, code in the mouseClicked() method of the MouseListener object generates a synthetic or counterfeit ActionEvent object and posts it to the SystemEventQueue. The code in the Label's MouseListener object impersonates the Button object by placing the identification of the Button object into the "source" field of the counterfeit ActionEvent object. The runtime system delivers the counterfeit ActionEvent object to the ActionListener object registered on the Button object. The final result is that clicking on the Label object invokes the actionPerformed() method registered on the Button object, so clicking on the Label object has exactly the same result as clicking on the Button object. The program was tested using JDK 1.1.1 (and later JDK 1.1.3) and Win95. An interesting sidelight is that the counterfeit button constructed from the Label object is more responsive than the real button. In other words, the counterfeit button can service mouse clicks at a more rapid rate than the real button. */ import java.awt.*; import java.awt.event.*; //========================================================= public class Event31 extends Frame{ public static void main(String[] args){ Event31 displayWindow = new Event31();//instantiate obj }//end main //------------------------------------------------------- public Event31(){//constructor setTitle("Copyright 1997, R.G.Baldwin"); setLayout(new FlowLayout()); Button clickMeButton = new Button("Click Me"); Label colorMeLabel = new Label("Color Me"); Label clickMeLabel = new Label("Click Me"); add(clickMeButton);//add components to the Frame object add(colorMeLabel); add(clickMeLabel); setSize(250,100);//set frame size setVisible(true);//display the frame //Register listener objects clickMeLabel.addMouseListener( new MyMouseListener(clickMeButton)); clickMeButton.addActionListener( new MyActionListener(colorMeLabel)); //terminate when Frame is closed this.addWindowListener(new Terminate()); }//end constructor }//end class Event31 //========================================================= /*This MouseListener class is used to monitor for mouse clicks on a Label object. Whenever the user clicks on the label, the code in an object of this class creates a counterfeit ActionEvent object and posts it to the SystemEventQueue. The source of the event is specified to be a particular Button object that is passed in when an object of this class is instantiated. Thus, the Label object "claims" to be the Button object and posts ActionEvent objects that are interpreted by the runtime system as originating at the Button object. The type of ActionEvents generated are ACTION_PERFORMED events. The events are automatically delivered to the actionPerformed() method of an ActionListener object registered on the button. */ class MyMouseListener extends MouseAdapter{ Button clickMeButton;//reference to the Button //------------------------------------------------------- MyMouseListener(Button inButton){//constructor clickMeButton = inButton;//save reference to Button }//end constructor //------------------------------------------------------- //overridden mouseClicked() method public void mouseClicked(MouseEvent e){ //Note that the following is a single statement Toolkit.getDefaultToolkit(). getSystemEventQueue(). postEvent(new ActionEvent(clickMeButton, ActionEvent. ACTION_PERFORMED, "counterfeit")); }//end overridden mouseClicked() method }//end MyMouseListener //========================================================= /*This ActionListener class is used to instantiate a Listener object for the Button object. Whenever the button is clicked, or a counterfeit ActionEvent is posted with the Button as the specified source object, the code in an object of this class toggles the background color of a Label object back and forth between yellow and blue.*/ class MyActionListener implements ActionListener{ int toggle = 0; Label myLabel; //------------------------------------------------------- MyActionListener(Label inLabel){//constructor myLabel = inLabel; }//end constructor //------------------------------------------------------- public void actionPerformed(ActionEvent e){ if(toggle == 0){ toggle = 1; myLabel.setBackground(Color.yellow); }else{ toggle = 0; myLabel.setBackground(Color.blue); }//end else }//end actionPerformed() }//end class myActionListener //========================================================= class Terminate extends WindowAdapter{ public void windowClosing(WindowEvent e){ //terminate the program when the window is closed System.exit(0); }//end windowClosing }//end class Terminate //========================================================= |
A - See the specifications and the
solution below.
/*File SampProg133.java Copyright 1997, R.G.Baldwin Without viewing the solution that follows, write a Java application that replicates the behavior of the application named Event31.java (discussed in lesson 106) with the following changes. This is an upgrade to the original version of Event31. In particular, in its original form, there is no visual indication when the user clicks on the Label object identified by the Click Me caption. Since this Label object is being used to simulate a Button object, a visual indication that the Label object has been clicked would be appropriate. In your upgraded version, the white Label object which originally had the Click Me caption will appear as a magenta colored rectangle when the program starts and will not display a caption. When the user clicks the magenta Label object, the caption "ouch" will momentarily appear and disappear in synchronism with the down stroke and the up stroke of the left mouse button. The caption will appear on the down stroke and will disappear on the upstroke. In addition to the above, make your name appear in the banner at the top of the Frame object. The upgraded version of the program has been tested using JDK 1.1.3 under Win95. */ //========================================================= import java.awt.*; import java.awt.event.*; //========================================================= public class SampProg133 extends Frame{ public static void main(String[] args){ //instantiate obj SampProg133 displayWindow = new SampProg133(); }//end main //------------------------------------------------------- public SampProg133(){//constructor setTitle("Copyright 1997, R.G.Baldwin"); setLayout(new FlowLayout()); Button clickMeButton = new Button("Click Me"); Label colorMeLabel = new Label("Color Me"); Label clickMeLabel = new Label(" "); clickMeLabel.setBackground(Color.magenta); add(clickMeButton);//add components to the Frame object add(colorMeLabel); add(clickMeLabel); setSize(300,100);//set frame size setVisible(true);//display the frame //Register listener objects clickMeLabel.addMouseListener( new MyMouseListener(clickMeButton,clickMeLabel)); clickMeButton.addActionListener( new MyActionListener(colorMeLabel)); //terminate when Frame is closed this.addWindowListener(new Terminate()); }//end constructor }//end class SampProg133 //========================================================= /*This MouseListener class is used to monitor for mouse clicks on a Label object. Whenever the user clicks on the label, the code in an object of this class creates a counterfeit ActionEvent object and posts it to the SystemEventQueue. The source of the event is specified to be a particular Button object that is passed in when an object of this class is instantiated. Thus, the Label object "claims" to be the Button object and posts ActionEvent objects that are interpreted by the runtime system as originating at the Button object. The type of ActionEvents generated are ACTION_PERFORMED events. The events are automatically delivered to the actionPerformed() method of an ActionListener object registered on the button. */ class MyMouseListener extends MouseAdapter{ Button clickMeButton;//reference to the Button Label clickMeLabel;//reference to the Label //------------------------------------------------------- //constructor MyMouseListener(Button inButton,Label inLabel){ clickMeButton = inButton;//save reference to Button clickMeLabel = inLabel;//save reference to Label }//end constructor //------------------------------------------------------- //overridden mouseClicked() method public void mouseClicked(MouseEvent e){ //Note that the following is a single statement Toolkit.getDefaultToolkit(). getSystemEventQueue(). postEvent(new ActionEvent(clickMeButton, ActionEvent. ACTION_PERFORMED, "counterfeit")); }//end overridden mouseClicked() method //------------------------------------------------------ //overridden mousePressed() method public void mousePressed(MouseEvent e){ clickMeLabel.setText(" ouch "); }//end overridden mousePressed() method //------------------------------------------------------ //overridden mouseReleased() method public void mouseReleased(MouseEvent e){ clickMeLabel.setText(" "); }//end overridden mousePressed() method }//end MyMouseListener //========================================================= /*This ActionListener class is used to instantiate a Listener object for the Button object. Whenever the button is clicked, or a counterfeit ActionEvent is posted with the Button as the specified source object, the code in an object of this class toggles the background color of a Label object back and forth between yellow and blue.*/ class MyActionListener implements ActionListener{ int toggle = 0; Label myLabel; //------------------------------------------------------- MyActionListener(Label inLabel){//constructor myLabel = inLabel; }//end constructor //------------------------------------------------------- public void actionPerformed(ActionEvent e){ if(toggle == 0){ toggle = 1; myLabel.setBackground(Color.yellow); }else{ toggle = 0; myLabel.setBackground(Color.blue); }//end else }//end actionPerformed() }//end class myActionListener //========================================================= class Terminate extends WindowAdapter{ public void windowClosing(WindowEvent e){ //terminate the program when the window is closed System.exit(0); }//end windowClosing }//end class Terminate //========================================================= |