SINGLE EVENT HANDLING Event handling is the process of responding to asynchronous events as they occur during the program run. An event is an action that occurs externally to your program and to which your program must respond. Events are asynchronous, meaning that they can happen anytime during the program run; they are not tied to the run-time of any specific part of your program. The basic event handling model is for every event to be tied to an event handler some program text that is coded to correctly respond to the event. This event handler is called by the control program which is the virtual machine, operating system or whatever whenever the event occurs. The Java model implements this by providing various listener interfaces in the java.awt.event package. Each listener interface is meant to listen for a particular type of event and it contains a special method that is called when an event of that type occurs. You, the programmer, set up the event handling in your program as follows: 1. Import what you need from the java.awt.event package. 2. Choose the listener interface that listens for the type of events you need to handle. 3. Create a subclass that implements it. 4. Within your subclass, morph each method that handles an event in a manner appropriate to your need. 5. Use your newly created subclass to build an event listener object, which listens for the event to occur. 6. Register the event listener object with the GUI component that can trigger the event. With this done, the running program behaves as follows: When an external event happens to a GUI component... A. The GUI component notifies whatever event listener is registered to it and sends it the event object. B. The event listener executes its special method. C. Your code (that you implemented in step 3 above) executes, handling the event. Single Event Handling Page 1
Example The following application SingleButton creates the GUI shown to the right. We are going to modify the application so that, when the user clicks the button, the number that labels it is incremented. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import javax.swing.*; import java.awt.*; public class SingleButton extends JFrame public static void main ( String [] args ) new SingleButton( ); // declare here to increase scope to entire application JButton button; public SingleButton( ) // window management super( "Single Button" ); this.setdefaultcloseoperation( JFrame.EXIT_ON_CLOSE ); // button configuration button = new JButton( "0.0" ); button.settooltiptext( "Click to increment" ); // window configuration this.setlayout( new FlowLayout( ) ); this.add( button ); this.setsize( 300, 150 ); this.setvisible( true ); Step 1 is to import the event handling classes to the program. Add this line to the top of the file: import java.awt.event.*; Single Event Handling Page 2
Step 2 is to determine which listener interface that for the type of events generated by the GUI component you re programming. A JButton object generates an ActionEvent object, which is listened to by an ActionListener interface. Step 3 is to create a subclass that implements the appropriate listener interface in this example, the ActionListener interface. Here s the code: private class MyListener implements ActionListener... Step 4 is to implement the methods of the interface so that your class does what you want it to do. All the methods of an interface must be implemented by your class. Fortunately, the ActionListener interface only has one method in it named actionperformed. Here s its description: void actionperformed( ActionEvent e ) // This method is called when an action occurs. The JVM passes // the ActionEvent object describing the action as an argument. We want the action to increment the number that labels the button. So we code the actionperformed method to grab the text of the button label, convert it to a floating-point value, increment it, convert the result back to text and place it on the button. Here s the code: // steps 2 & 3: create subclass implementing the appropriate // listener interface private class MyListener implements ActionListener // step 3: make the handler method do what I need. public void actionperformed( ActionEvent e ) // get text from button and parse into a double double x = Double.parseDouble( button.gettext( ) ); // increment it and put it back button.settext( Double.toString( ++x ) ); Single Event Handling Page 3
Step 5 is to create an object from your newly created subclass. // step 5: create an object to listen for the event MyListener listener = new MyListener( ); Step 6 is to register the event listener object with the GUI component that can trigger the event, in this example the JButton. // step 6: register the event listener with the button button.addactionlistener( listener ); Code Placement is complicated only by Java s scope rules. Since the button is configured in the application s constructor and manipulated within the actionperformed method, its scope must include both and so it must be declared in the class block outside any other block. Similarly, the MyListener class can be placed anywhere within the class block outside any other block. This arrangement is called a nested class since it is wholly contained within another class. It is a member of the application class and has access to everything in the application s scope. The code for steps 5 and 6 are placed within the application s constructor since they are part of the configuration of the GUI. import javax.swing.*; import java.awt.*; public class SingleButton extends JFrame public static void main ( String [] args ) new SingleButton( ); // declare here to increase scope to entire application JButton button; public SingleButton( ) // window management super( "Single Button" ); this.setdefaultcloseoperation( JFrame.EXIT_ON_CLOSE ); // button configuration button = new JButton( "0.0" ); button.settooltiptext( "Click to increment" ); // window configuration this.setlayout( new FlowLayout( ) ); this.add( button ); this.setsize( 300, 150 ); this.setvisible( true ); import java.awt.event.*; // steps 2 & 3: create subclass implementing the appropriate // listener interface private class MyListener implements ActionListener // step 3: make the handler method do what I need. public void actionperformed( ActionEvent e ) // get text from button and parse into a double double x = Double.parseDouble( button.gettext( ) ); // increment it and put it back button.settext( Double.toString( ++x ) ); // step 5: create an object to listen for the event MyListener listener = new MyListener( ); // step 6: register the event listener with the button button.addactionlistener( listener ); Single Event Handling Page 4
This diagram shows the relationship between the objects in the example application created by steps marked 3 and 4. button.text.registeredlistener... listener.actionperformed... void actionperformed( ActionEvent e ) // morphed code What the JVM Does As the program runs, the action listener (listener in the above example) sits in the background waiting for an event to occur. When the user clicks the button named button... A. The JVM it generates a java.awt.event.actionevent object. B. The button passes the ActionEvent object to parameter e of the actionperformed method. C. The actionperformed method executes. D. The main program thread of execution waits as all this happens. E. When actionperformed is finished, the main thread resumes. Single Event Handling Page 5
Exercises 1. Enter the application SingleButton into jgrasp and edit it by adding the code from the example on pages 2 through 4. Be sure to follow the recommended code placement explained on page 4. Compile and run the application and observe its operation. 2. With the SingleButton application in jgrasp, click the line numbers button ( you can see the line numbers. ) so that 3. In jgrasp s main window, set a breakpoint at line 23: double x = Double.parseDouble( button.gettext( ) ); To set the breakpoint, move the mouse cursor to the gray bar at the left of your code. It will display a red dot. Click the mouse to set the breakpoint. 4. Start jgrasp s debugger by clicking the Ladybug button. The application will execute, display the GUI window and wait for user interaction. 5. Click the button. Execution now halts at line 23 of the actionperformed method. See if you can retrace the sequence of JVM events initiated by your button click. HINT: Consider the diagram on page 5. What object was created by the JVM upon the button click? How did the JVM know which actionperformed method to call? 6 Using the Step button step through the execution of the actionperformed method and observe the alteration of the GUI window. 7. Comment out line 40: button.addactionlistener( listener ); Recompile and run the program. Why does it not work? Considering the diagram on page 5, which link in the chain has been broken? Single Event Handling Page 6
For each of the following write a Java program (application or applet or both) that adheres to the given specifications. 8. Create the GUI described below: 1. It contains two GUI components. 1.1. A JTextField object containing 0 with horizontal right alignment. 1.2. A JButton object, the up button, containing some character or image resembling an up arrow. 2. The window title must be x s Spinner where x is your name. Here s how the GUI must behave: 3. The up button, when clicked, must increment the text field value. 4. When the text field value reaches the max value of 10, the next button click returns the text field value to zero. For this version of the program, do the following: 5. Make the JTextField object noneditable. 6. Hard code the maximum value as a constant identifier : final int MAX_VALUE = 10; 9. Create the GUI described below: 1. It contains two GUI components. 1.1. A JTextField object containing 1 of 20. The 1 is the record number and the 20 is the last record number. 1.2. A JButton object, the next button, which contains a character or image resembling a right arrow. 1.3. The window title must be x s Record Browser where x is your name. Here s how the GUI must behave: Single Event Handling Page 7
2. The next button, when clicked, must increment the record number, leaving the last record number the same. The GUI on the right would appear after one button click. 3. When the record number reaches the last record number, as shown to the right, the next button is disabled. For this version of the program, do the following: 4. Make the JTextField object noneditable. 5. Hard code the last record number as a constant identifier : final int LAST_REC_NUM = 20; 10. This exercise is an extension of Exercise 9 of the topic GUI Applications. Create the GUI described below: 1. It contains two GUI components. 1.1. A JLabel object containing Enter your Birthday. 1.2. A JTextField object. 1.3. A JButton object, the GO button. Here s how the GUI must behave: 2. The text field must accept user input. 3. The GO button must calculate the age of the user using the birth date contained in the text field. 3.1. Calculate the age of the user in years, months and days. HINT: Study the descriptions of the java.time.period class found in the Java API and the Oracle Java tutorials. 4. Display the age within a JLabel object after the GO button. 4.1. Display Happy Birthday within a JLabel object if the current month and day is the same as the user s birth month and day. Single Event Handling Page 8