Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 
Search the JavaFAQ.nu
1000 Java Tips ebook

1000 Java Tips - Click here for the high resolution copy!1000 Java Tips - Click here for the high resolution copy!

Java Screensaver, take it here

Free "1000 Java Tips" eBook is here! It is huge collection of big and small Java programming articles and tips. Please take your copy here.

Take your copy of free "Java Technology Screensaver"!.

Lecture 18: Writing event listeners with best examples, Part II

JavaFAQ Home » Java Lectures by Anatoliy Malyarenko Go to all tips in Java Lectures by Anatoliy Malyarenko


Bookmark and Share

General information about writing event listeners

Part I was published here

Design considerations

You have many choices on how to implement an event listener. We can't recommend a specific approach because one solution won't suit all situations. However, we can give you some hints and show you some techniques that you might see, even if you don't use the same solution in your program.

For example, you might choose to implement separate classes for different kinds of event listeners. This can be an easy architecture to maintain, but many classes can also mean reduced performance.

When designing your program, you might want to implement your event listeners in a class that is not public, but somewhere more hidden. A private implementation is a more secure implementation.

If you have a very specific kind of simple event listener, you might be able to avoid creating a class at all by using the EventHandler class.

Getting event information: event objects

Every event-listener method has a single argument -- an object that inherits from the EventObject class. Although the argument always descends from EventObject, its type is generally specified more precisely. For example, the argument for methods that handle mouse events is an instance of MouseEvent, where MouseEvent is an indirect subclass of EventObject.

The EventObject class defines one very useful method:

Code:

  Object getSource()

that returns the object that fired the event. Note that the getSource method returns an Object. Event classes sometimes define methods similar to getSource, but that have more restricted return types. For example, the ComponentEvent class defines a getComponent method that -- just like getSource -- returns the object that fired the event. The difference is that getComponent always returns a Component.

Often, an event class defines methods that return information about the event. For example, you can query a MouseEvent object for information about where the event occurred, how many clicks the user made, which modifier keys were pressed, and so on.

Low-level events and semantic events

Events can be divided into two groups: low-level events and semantic events. Low-level events represent window-system occurrences or low-level input. Everything else is a semantic event.

Examples of low-level events include mouse and key events -- both of which result directly from user input. Examples of semantic events include action and item events. A semantic event might be triggered by user input; for example, a button customarily fires an action event when the user clicks it, and a text field fires an action event when the user presses Enter. However, some semantic events aren't triggered by low-level events, at all. For example, a table-model event might be fired when a table model receives new data from a database.

Whenever possible, you should listen for semantic events rather than low-level events. That way, you can make your code as robust and portable as possible. For example, listening for action events on buttons, rather than mouse events, means that the button will react appropriately when the user tries to activate the button using a keyboard alternative or a look-and-feel-specific gesture. When dealing with a compound component such as a combo box, it's imperative that you stick to semantic events, since you have no reliable way of registering listeners on all the look-and-feel-specific components that might be used to form the compound component.

Event adapters

Some listener interfaces contain more than one method. For example, the MouseListener interface contains five methods:

Code:

  mousePressed,
  mouseReleased,
  mouseEntered,
  mouseExited, and
  mouseClicked.

Even if you care only about mouse clicks, if your class directly implements MouseListener, then you must implement all five MouseListener methods. Methods for those events you don't care about can have empty bodies. Here's an example:

Code:



someObject.addMouseListener(this);
...
/* Empty method definition. */
public void mousePressed(MouseEvent e) { }

/* Empty method definition. */
public void mouseReleased(MouseEvent e) { }

/* Empty method definition. */
public void mouseEntered(MouseEvent e) { }

/* Empty method definition. */
public void mouseExited(MouseEvent e) { }
public void mouseClicked(MouseEvent e) {
    ...//Event listener implementation goes here...
}


The resulting collection of empty method bodies can make code harder to read and maintain. To help you avoid implementing empty method bodies, the API generally includes an adapter class for each listener interface with more than one method. For example, the MouseAdapter class implements the MouseListener interface. An adapter class implements empty versions of all its interface's methods.

To use an adapter, you create a subclass of it and override only the methods of interest, rather than directly implementing all methods of the listener interface. Here is an example of modifying the preceding code to extend MouseAdapter. By extending MouseAdapter, it inherits empty definitions of all five of the methods that MouseListener contains.

Code:

public class MyClass extends MouseAdapter {
    ...
    someObject.addMouseListener(this);
    ...
    public void mouseClicked(MouseEvent e) {
        ...//Event listener implementation goes here...
    }
}

Inner classes

What if you want to use an adapter class, but don't want your public class to inherit from an adapter class? For example, suppose you write an applet, and you want your Applet subclass to contain some code to handle mouse events. Since the Java language doesn't permit multiple inheritance, your class can't extend both the Applet and MouseAdapter classes. A solution is to define an inner class -- a class inside of your Applet subclass -- that extends the MouseAdapter class.

Inner classes can also be useful for event listeners that implement one or more interfaces directly.

Code:


public class MyClass extends Applet {
    ...
    someObject.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent e) {
            ...//Event listener implementation goes here...
        }
    });
    ...
    }
}

When considering whether to use an inner class, keep in mind that application startup time and memory footprint are typically directly proportional to the number of classes you load. The more classes you create, the longer your program takes to start up and the more memory
it will take. As an application developer you have to balance this with other design constraints you may have. We are not suggesting you turn your application into a single monolithic class in hopes of cutting down startup time and memory footprint -- this would lead to unnecessary headaches and maintenance burdens.

You can create an inner class without specifying a name -- this is known as an anonymous inner class. While it might look strange at first glance, anonymous inner classes can make your code easier to read because the class is defined where it is referenced.

However, you need to weigh the convenience against possible performance implications of increasing the number of classes.

Here's an example of using an anonymous inner class:

Code:



public class MyClass extends Applet {
    ...
    someObject.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent e) {
            ...//Event listener implementation goes here...
        }
    });
    ...
    }
}

Inner classes work even if your event listener needs access to private instance variables from the enclosing class. As long as you don't declare an inner class to be static, an inner class can refer to instance variables and methods just as if its code is in the containing class. To make a local variable available to an inner class, just save a copy of the variable as a final local variable.

Implementing listeners for commonly handling events

How to write an action listener?

Action listeners are probably the easiest -- and most common -- event handlers to implement. You implement an action listener to respond to the user's indication that some implementation-dependent action should occur.

When the user clicks a button, chooses a menu item or presses Enter in a text field, an action event occurs. The result is that an actionPerformed message is sent to all action listeners that are registered on the relevant component.

Here is the action event handling code example from an applet named Beeper:

Code:


public class Beeper ...
        implements ActionListener {
    ...
    //where initialisation occurs:

    button.addActionListener(this);
    ...
    public void actionPerformed(ActionEvent e) {
        Toolkit.getDefaultToolkit().beep();
    }
}

How to write an item listener?

Item events are fired by components that implement the ItemSelectable interface. Generally, ItemSelectable components maintain on/off state for one or more items. The Swing components that fire item events include check boxes, check box menu items, and combo boxes.

Here is some item-event handling code example taken from ComponentEventDemo.java:

Code:



checkbox.addItemListener(this);
...
public void itemStateChanged(ItemEvent e) {
    if (e.getStateChange() == ItemEvent.SELECTED) {
        label.setVisible(true);
        ...
    } else {
        label.setVisible(false);
    }
}




 Printer Friendly Page  Printer Friendly Page
 Send to a Friend  Send to a Friend

.. Bookmark and Share

Search here again if you need more info!
Custom Search



Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy