Working with events

These are the topics covered in this chapter:


Fast track to events

The component writer works with events in three ways:

Fast track to selecting an existing event set

To select an existing event set,

Fast track to creating a new event set

To create a new event set,

  1. Create a new event class by extending java.util.EventObject or one of its subclasses.

  2. Create a new event-listener interface by extending java.util.EventListener or one of its subclasses, or by writing one of your own.

Fast track to making a component into an event source

To make a component into an event source, capable of generating an event and sending it to listeners,

  1. Write the event registration (add- and remove-listener) methods, following JavaBeans design patterns.

  2. Write an event-generation method that creates an event object and passes it to listening components by calling a method in the listener's event-listener interface.

  3. Call this event-generation method when the event should occur.

Fast track to making a component a listener

To make a component listen for an event, capable of responding to it,

  1. Implement an interface that extends the java.util.EventListener interface.
  2. Call the add event-listener method of the source component, registering your component as a listener.

Usually you aren't concerned with the listener side of events because JBuilder handles the previous two steps automatically. When the user selects an event on the Event tab of the Component Inspector and double-clicks it, JBuilder links the event with a container method, presenting an empty method in the source code for the user to fill in. Behind the scenes JBuilder has extended an event-listener interface and registered the container as a listener for the event.

For more fast-track information about building JavaBeans components, see BeansExpress.


What are events?

When an application runs, occurrences such as mouse clicks, key presses, windows opening and closing, and many others can potentially change how the application behaves. An event is the link between these occurrences and the user's code that tells the application how to respond. The JavaBeans component model defines how to create methods and interfaces so that JBuilder can recognize component events, display those events within JBuilder's environment, and allow the component user to select which events the component will respond to.

Components are affected by events in two ways:

The component user writes the method that tells the application what to do when the user presses a key or makes a choice in a list control. The component writer writes the code that determines which event(s) each component can generate, and (occasionally) which components can respond or listen to events.

Components might be able to generate many events, but only a small number of those events are likely to be used by any pariticular component user. A Java button, for instance, can generate actionPerformed, mousePressed, mouseReleased, mouseMoved, and many other events, yet a user might use only one of these. Because you won't know exactly how the component will be used and which events will be required, you should design the component so that it can generate all appropriate events.

How events flow from the event source to the event listener

There are usually at least three pieces of code involved in an event transaction. This discussion refers to them as A (the event source), B (the event listener), and C (the container or other code where everything is bound together).

Usually in JBuilder,

Why JBuilder uses action adapters

Theoretically, the container C could directly implement the event-listener interface, and register itself, instead of the action adapter, as the event listener. But suppose more than one component could generate a particular event. The event handler would need to determine which component generated the event before it could handle the event properly. Using the action adapter approach, each adapter, and therefore, each event-handling method, represents a single source-listener pair.

How component users view events

When using the UI Designer, the user sees an event primarily as the event handling method that must be implemented in the class that contains the component. For example, suppose the user places a Button named button1 into a container called Frame1, and wants something to happen when button1 is pressed. The user selects button1 in the Frame1 Designer, goes to the Event page of the Component Inspector, and double-clicks actionPerformed. (actionPerformed is the event generated when a button is pressed). JBuilder switches to the Frame1 source code and inserts an event-handling method into Frame1 that is called when that event occurs. The method is called button1_actionPerformed() by default, and the body of the method is initially empty. The user inserts code into the method to respond to the button press.

Behind the scenes, JBuilder also generates additional code in the Frame1.java file to handle the other aspects of event listening. It generates an action adapter class that implements the ActionListener interface, instantiates the class in Frame1, and registers it as a listener for the button1 event by calling button1.addActionListener(). All of this code is visible to the user in the source code, but the primary focus for the user is to fill in the event-handling method that the action adapter calls when the event occurs.

A user sees all of the potential events from button1 listed on the Events page of JBuilder's Component Inspector. As the component writer, you are responsible for creating the component class in such a way that all the events it generates will appear in the Component Inspector. You do this by making the component a JavaBeans event source, as you'll see later. All the user must do is write the code that fills in the event-handling method.

An advanced user could hook up events in other ways. For example, if component A is an event source and component B is an event listener, and class C is where A and B are instantiated, the user could put code that calls a.addListener(b) into A, B, C, or any other class, using various mechanisms of determining when and how the components should be connected together. Usually, however, JBuilder creates a simple action adapter to serve as component B, and the container class C is the site where the objects are instantiated and the event listener registration and event handling are performed. In this simplified JBuilder model, the components that the user selects from the Component Palette do not need to be event listeners, only event sources.

How component writers view events

Component writers see events primarily as something that can be fired by the component being written.

More rarely, a component writer can decide to make the component capable of being an event listener, although event listening is usually entirely handled automatically for the user by JBuilder's visual design tools.

To make a component capable of firing events, follow these steps:

  1. Determine what kind of event needs to be fired, and select an appropriate existing event set from Java AWT or JBCL, or create a new event set.

  2. Create event registration mechanisms for the component.

  3. Create an event notification / propogation mechanism for the event.

  4. Determine where in the component's code the event is fired and call the event notification mechanism from that point in the code.

The following sections explain how to do these things.


Event sets

An event set defines a type of event, what it communicates, and what is required to generate and to listen to the event. An event set consists of

There are some types of events that do not pass objects, merely simple parameters. These types of events are called cracked events, but they are rare. The borland.jbcl.dataset package uses cracked events in many cases, but the components in the java.awt and borland.jbcl.control packages usually generate events that pass event objects.

The Java AWT package provides several predefined event sets, such as focus events, mouse events, mouse move events, key events, and so on. These event sets include interfaces, event objects, and methods.

For example, consider the key events. The key events set includes the KeyListener interface (which defines the keyPressed(), keyReleased(), and keyTyped() methods), and the KeyEvent class. A component that generates key events must define the addKeyListener and removeKeyListener registration methods.

In the key events example, note the naming pattern convention; the event name "Key" appears in the listener interface, its methods, the event object, and the registration methods. Use this same naming pattern for all event sets you create.

See Component events for more information about Java's standard events.

Besides the Java AWT event sets, JBCL provides additional event sets for specific purposes. For example, several event sets are defined for database programming in the dataset package. Again, because these events sets are predefined, you don't have to create them yourself. See Events in the JavaBeans Component Library for more information about JBCL custom event sets.

Usually the predefined event sets such as the key events set are sufficient for your programming needs. You can, however, create your own events sets if you choose.

If you want to have a component generate events, you must define in the component the event-registration methods so that other code can attach one or more event listeners to the component.

It is the presence of the event-registration methods in a source component that makes the events appear on the Events page of the Component Inspector when the user selects the component on the UI Designer.

See also:
Working with existing event sets
Creating custom event sets


About event-listener interfaces

Standard JavaBeans events are grouped into a series of Java interfaces; you can identify them by the word Listener as part of the source file name (for example, KeyListener.java). All of them extend java.util.EventListener. Java defines the event listeners as interfaces so you can implement them in your components. Here is some of the code from the KeyListener.java source file:

public interface KeyListener extends EventListener
{
  void keyTypes(KeyEvent e);     // a key is pressed and released
  void keyPressed(KeyEvent e);   // a key is pressed
  void keyReleased(KeyEvent e);  // a key is released
// end of example code

The KeyListener interface defines all of the types of keyboard events to which Java components can listen and respond. Each specific type of key event has a separate method within the interface. For example, there is a keyPressed() method for a key press event, and a keyReleased() method for a key release event.

See also:
Listening for an event occurrence


Working with existing event sets

Most of the time you'll be working with existing event sets, rather than defining your own. If you use existing event sets, your task is easier. You will merely need to select the event set that you want to use, from the Java AWT events or JBCL events.

If you are building a component that derives from another component, it already generates all of the events that the superclasses generate. For example, if your component extends java.awt.Component or one of its subclasses, then your component automatically generates a number of events, such as key and mouse events. You might not need to do any additional programming to make your component capable of firing these events.

You can use BeansExpress to begin your component development. Choose File|New|BeansExpress and use the NewBean snippet to start your new component. The snippet creates the shell of a new UI component. The superclass has the event listeners for ActionListener registration. Also, each superclass has a convenient fireExampleActionEvent method that you can call to fire an ActionEvent. For more information, see BeansExpress.

To make your component capable of generating an event when no superclass can generate it,

You seldom need to make your component an event listener, as the event listener is usually provided automatically by JBuilder's visual design tools in the container class being created by the user. If, however, you decide you want your component to be able to listen for particular events, you must implement the appropriate <Event>Listener interfaces for the event sets you choose. For more information, see event-listener interfaces and Listening for an event occurrence