Basics of Event Handling Core Java

Any operating environment that supports GUIs constantly monitors events such as key strokes or mouse clicks. The operating environment reports these events to the programsthat are running. Each program then decides what, if anything, to do in responseto these events. In languages like Visual Basic, the correspondence between events andcode is obvious. One writes code for each specific event of interest and places the codein what is usually called an event procedure. For example, a Visual Basic button named “HelpButton” would have a Help Button _Click event procedure associated with it. Thecode in this procedure executes whenever that button is clicked. Each Visual Basic GUIcomponent responds to a fixed set of events, and it is impossible to change the eventsto which a Visual Basic component responds.

On the other hand, if you use a language like raw C to do event-driven programming,you need to write the code that constantly checks the event queue for what the operating environment is reporting. (You usually do this by encasing your code in a loop witha massive switch statement!) This technique is obviously rather ugly, and, in any case, itis much more difficult to code. The advantage is that the events you can respond to arenot as limited as in languages, like Visual Basic, that go to great lengths to hide the eventqueue from the programmer.

The Java programming environment takes an approach somewhat between the VisualBasic approach and the raw C approach in terms of power and, therefore, in resulting complexity. Within the limits of the events that the AWT knows about, you completelycontrol how events are transmitted from the event sources (such as buttons or scrollbars)to event listeners. You can designate any object to be an event listener—in practice, youpick an object that can conveniently carry out the desired response to the event. Thisevent delegation model gives you much more flexibility than is possible with Visual Basic,in which the listener is predetermined.

Event sources have methods that allow you to register event listeners with them. Whenan event happens to the source, the source sends a notification of that event to all the listener objects that were registered for that event.

As one would expect in an object-oriented language like Java, the information about the event is encapsulated in an event object. In Java, all event objects ultimately derive fromthe class java.util.EventObject. Of course, there are subclasses for each event type, such as Action Event and Window Event.

Different event sources can produce different kinds of events. For example, a button cansend ActionEvent objects, whereas a window can send Window Event objects.

To sum up, here’s an overview of how event handling in the AWT works:

  • A listener object is an instance of a class that implements a special interface called(naturally enough) a listener interface.
  • An event source is an object that can register listener objects and send them eventobjects.325
  • The event source sends out event objects to all registered listeners when that eventoccurs.
  • The listener objects will then use the information in the event object to determinetheir reaction to the event.

the relationship between the event handling classes and interfaces.

Relationship between event sources and listeners

Relationship between event sources and listeners

Here is an example for specifying a listener:

Now the listener object is notified whenever an “action event” occurs in the button. For buttons, as you might expect, an action event is a button click.

To implement the Action Listener interface, the listener class must have a method calledactionPerformed that receives an ActionEvent object as a parameter.

Whenever the user clicks the button, the JButton object creates an Action Event object and calls listener.action Performed (event), passing that event object. An event source such as abutton can have multiple listeners. In that case, the button calls the action Performed methodsof all listeners whenever the user clicks the button.

the interaction between the event source, event listener, and eventobject.

Event notification

Event notification

Example: Handling a Button Click

As a way of getting comfortable with the event delegation model, let’s work through all details needed for the simple example of responding to a button click. For this example,we will show a panel populated with three buttons. Three listener objects are added asaction listeners to the buttons.

With this scenario, each time a user clicks on any of the buttons on the panel, the associated listener object then receives an ActionEvent that indicates a button click. In our sampleprogram, the listener object will then change the background color of the panel.

Before we can show you the program that listens to button clicks, we first need toexplain how to create buttons and how to add them to a panel.

You create a button by specifying a label string, an icon, or both in the button constructor.

Here are two examples:

A panel filled with buttons

A panel filled with buttons

Next, we need to add code that listens to these buttons. This requires classes that implement the ActionListener interface, which, as we just mentioned, has one method: action Performed,whose signature looks like this:

NOTE: The ActionListener interface we used in the button example is not restricted to buttonclicks. It is used in many separate situations:

  • When an item is selected from a list box with a double click
  • When a menu item is selected
  • When the ENTER key is clicked in a text field
  • When a certain amount of time has elapsed for a Timer component

You will see more details in this section and the next. The way to use the ActionListener interface is the same in all situations: the actionPerformedmethod (which is the only method in Action Listener) takes an object of type ActionEvent as aparameter. This event object gives you information about the event that happened.

When a button is clicked, we want the background color of the panel to change to a particular color. We store the desired color in our listener class.

We then construct one object for each color and set the objects as the button listeners.

For example, if a user clicks on the button marked “Yellow,” then the action Performed method of the yellowAction object is called. Its background Color instance field is set toColor. YELLOW, and it can now proceed to set the panel’s background color.

Just one issue remains. The ColorAction object doesn’t have access to the button Panel variable.You can solve this problem in two ways. You can store the panel in the Color Action object and set it in the Color Action constructor. Or, more conveniently, you can make Color -Action into an inner class of the Button Frame class. Its methods can then access the outerpanel automatically.

We follow the latter approach. Here is how you place the Color Action class inside the Button Frame class:

Look closely at the action Performed method. The Color Action class doesn’t have a button Panel field. But the outer Button Frame class does.

This situation is very common. Event listener objects usually need to carry out some action that affects other objects. You can often strategically place the listener class insidethe class whose state the listener should modify.

Listing below contains the complete program. Whenever you click one of the buttons, the appropriate action listener changes the background color of the panel.

ButtonTest.java

javax.swing.JButton

  • JButton(String label)
  • JButton(Icon icon)
  • JButton(String label, Icon icon)

constructs a button. The label string can be plain text or, starting with Java SE 1.3,

java.awt.Container

  • Component add(Component c)
    adds the component c to this container.
  • javax.swing.ImageIcon 1.2

  • ImageIcon(String filename)
    constructs an icon whose image is stored in a file.

Becoming Comfortable with Inner Classes

Some people dislike inner classes because they feel that a proliferation of classes and objects makes their programs slower. Let’s have a look at that claim. You don’t need a new class for every user interface component. In our example, all three buttons share the same listener class. Of course, each of them has a separate listener object. But these objects aren’t large. They each contain a color value and a reference to the panel. And the traditional solution, with if . . . else statements, also references the same color objects that the action listeners store, just as local variables and not as instance fields.

Here is a good example of how anonymous inner classes can actually simplify your code. If you look at the code of Listing above, you will note that each button requires the same treatment:

  1. Construct the button with a label string.
  2. Add the button to the panel.
  3. Construct an action listener with the appropriate color.
  4. Add that action listener.

Let’s implement a helper method to simplify these tasks:

Now you can make a further simplification. Note that the Color Action class is only needed once: in the make Button method. Therefore, you can make it into an anonymous class:

The action listener code has become quite a bit simpler. The action Performed method simply refers to the parameter variable backgroundColor. (As with all local variables that are accessed in the inner class, the parameter needs to be declared as final.)

No explicit constructor is needed. As you saw in earlier sections, the inner class mechanism automatically generates a constructor that stores all local final variables that are used in one of the methods of the inner class.

TIP: Anonymous inner classes can look confusing. But you can get used to deciphering them if you train your eyes to glaze over the routine code, like this:

That is, the button action sets the background color. As long as the event handler consists of just a few statements, we think this can be quite readable, particularly if you don’t worry about the inner class mechanics.

NOTE: You are completely free to designate any object of a class that implements the ActionListener interface as a button listener. We prefer to use objects of a new class that was expressly created for carrying out the desired button actions. However, some programmers are not comfortable with inner classes and choose a different strategy. They make the container of the event sources implement the Action Listener interface. Then, the container sets itself as the listener, like this:

Now the three buttons no longer have individual listeners. They share a single listener object, namely, the button frame. Therefore, the actionPerformed method must figure out which button was clicked.

As you can see, this gets quite messy, and we do not recommend it.

java.util.EventObject

  • Object getSource()
    returns a reference to the object where the event occurred.

java.awt.event.ActionEvent

  • String getActionCommand()
    returns the command string associated with this action event. If the action event originated from a button, the command string equals the button label, unless it has been changed with the setActionCommand method.

java.beans.EventHandler

  • static Object create(Class listenerInterface, Object target, String action)
  • static Object create(Class listenerInterface, Object target, String action, String eventProperty)
  • static Object create(Class listenerInterface, Object target, String action,

String eventProperty, String listener Method)
constructs an object of a proxy class that implements the given interface. Either the named method or all methods of the interface carry out the given action on the target object.

The action can be a method name or a property of the target. If it is a property, its setter method is executed. For example, an action "text" is turned into a call of the setText method.

The event property consists of one or more dot -separated property names. The first property is read from the parameter of the listener method. The second property is read from the resulting object, and so on. The final result becomes the parameter of the action. For example, the property "source.text" is turned into calls to the getSource and getText methods.

Creating Listeners Containing a Single Method Call

Java SE 1.4 introduces a mechanism that lets you specify simple event listeners without programming inner classes. For example, suppose you have a button labeled “Load” whose event handler contains a single method call:

But the EventHandler class can create such a listener automatically, with the call

If the listener calls a method with a single parameter that can be obtained from the event parameter, you can use another form of the create method. For example, the call

is equivalent to

The property names source and text turn into method calls getSource and getText.

Example: Changing the Look and Feel

By default, Swing programs use the Metal look and feel. There are two ways to change to a different look and feel. The first way is to supply a file swing .properties in the jre/libsubdirectory of your Java installation. In that file, set the property swing .defaultlaf to the class name of the look and feel that you want. For example:

Note that the Metal look and feel is located in the javax.swing package. The other lookand- feel packages are located in the com.sun.java package and need not be present in every Java implementation. Currently, for copyright reasons, the Windows and Macintosh look -and -feel packages are only shipped with the Windows and Macintosh versions of the Java runtime environment.

TIP: Because lines starting with a # character are ignored in property files, you can supply several look and feel selections in the swing.properties file and move around the # to select one of them:

You must restart your program to switch the look and feel in this way. A Swing program reads the swing.properties file only once, at startup.

The second way is to change the look and feel dynamically. Call the static UIManager.setLook- AndFeel method and give it the name of the look-and-feel class that you want. Then callthe static method Swing Utilities. update Component TreeUI to refresh the entire set of components.You need to supply one component to that method; it will find all others. TheUIManager .set Look And Feel method may throw a number of exceptions when it can’t findthe look and feel that you request, or when there is an error loading it. As always, weask you to gloss over the exception handling code and wait until next sections for a fullexplanation.

Here is an example showing how you can switch to the Motif look and feel in your program:

To enumerate all installed look and feel implementations, call

Then you can get the name and class name for each look and feel as

Switching the look and feel

Switching the look and feel

Following the advice of the preceding section, we use a helper method makeButton and an anonymous inner class to specify the button action, namely, to switch the look and feel. There is one fine point to this program. The actionPerformed method of the inner action listener class needs to pass the this reference of the outer PlafFrame class to the update -Component TreeUI method.

javax.swing.UIManager

  • static UIManager.LookAndFeelInfo[] getInstalledLookAndFeels()
  • gets an array of objects that describe the installed look-and-feel implementations.

  • static setLookAndFeel(String className)
    sets the current look and feel, using the given class name (such as
"javax.swing.plaf.metal.MetalLookAndFeel").

javax.swing.UIManager.LookAndFeelInfo

  • String getName()
    returns the display name for the look and feel.
  • String getClassName()
    returns the name of the implementation class for the look and feel.

Adapter Classes

Not all events are as simple to handle as button clicks. In a non-toy program, you will want to monitor when the user tries to close the main frame because you don’t want your users to lose unsaved work. When the user closes the frame, you want to put up a dialog and exit the program only when the user agrees.

When the program user tries to close a frame window, the JFrame object is the source of a Window Event. If you want to catch that event, you must have an appropriate listener object and add it to the frame’s list of window listeners.

The window listener must be an object of a class that implements the Window Listener interface. There are actually seven methods in the WindowListener interface. The framecalls them as the responses to seven distinct events that could happen to a window. Thenames are self-explanatory, except that “iconified” is usually called “minimized” under Windows. Here is the complete Window Listener interface: public interface Window Listener

NOTE: To find out whether a window has been maximized, install a Window State Listener.

As is always the case in Java, any class that implements an interface must implement all its methods; in this case, that means implementing seven methods. Recall that we are only interested in one of these seven methods, namely, the windowClosing method.

Of course, we can define a class that implements the interface, add a call to System.exit(0) in the window Closing method, and write do -nothing functions for the other six methods:

Typing code for six methods that don’t do anything is the kind of tedious busywork that nobody likes. To simplify this task, each of the AWT listener interfaces that has more than one method comes with a companion adapter class that implements all the methods in the interface but does nothing with them. For example, the WindowAdapter class has seven do-nothing methods. This means the adapter class automatically satisfies the

technical requirements that Java imposes for implementing the associated listener interface.You can extend the adapter class to specify the desired reactions to some, but notall, of the event types in the interface. (An interface such as ActionListener that has only a single method does not need an adapter class.)

Let us make use of the window adapter. We can extend the Window Adapter class, inherit six of the do-nothing methods, and override the window Closing method:

Now you can register an object of type Terminator as the event listener:

Whenever the frame generates a window event, it passes it to the listener object by calling one of its seven methods. Six of those methods do nothing; the window Closing method calls System.exit(0), terminating the application.

A window listener

A window listener

CAUTION: If you misspell the name of a method when extending an adapter class, then the compiler won’t catch your error. For example, if you define a method window IsClosing in a Window Adapter class, then you get a class with eight methods, and the windowClosing method does nothing.

Creating a listener class that extends the Window Adapter is an improvement, but we can go even further. There is no need to give a name to the listener object. Simply write frame .add Window Listener(new Terminator());

But why stop there? We can make the listener class into an anonymous inner class of the frame.

This code does the following:

  • Defines a class without a name that extends the WindowAdapter class
  • Adds a windowClosing method to that anonymous class (as before, this method exits the program)
  • Inherits the remaining six do-nothing methods from WindowAdapter
  • Creates an object of this class; that object does not have a name, either
  • Passes that object to the addWindowListener method

We say again that the syntax for using anonymous inner classes takes some getting used to. The payoff is that the resulting code is as short as possible.

java.awt.event.WindowListener

  • void windowOpened(WindowEvent e)
    is called after the window has been opened.
  • void windowClosing(WindowEvent e)
    is called when the user has issued a window manager command to close the window. Note that the window will close only if its hide or dispose method is called.
  • void windowClosed(WindowEvent e)
    is called after the window has closed.
  • void windowIconified(WindowEvent e)
    is called after the window has been iconified.
  • void windowDeiconified(WindowEvent e)
    is called after the window has been deiconified.
  • void windowActivated(WindowEvent e)
    is called after the window has become active. Only a frame or dialog can be active.
  • Typically, the window manager decorates the active window, for example, by highlighting the title bar.

  • void windowDeactivated(WindowEvent e)
    is called after the window has become deactivated.

java.awt.event.WindowStateListener

  • void windowStateChanged(WindowEvent event)
    is called after the window has been maximized, iconified, or restored to normal size.

java.awt.event.WindowEvent

  • int getNewState()
  • int getOldState()

returns the new and old state of a window in a window state change event. The returned integer is one of the following values:


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

Core Java Topics