站内搜索: 请输入搜索关键词
当前页面: 图书首页 > SWT: The Standard Widget Toolkit

1.3 Events and Listeners - SWT: The Standard Widget Toolkit

Previous Section  < Day Day Up >  Next Section

1.3 Events and Listeners

An event is simply an indication that something interesting has happened. Events, such as "mouse down" and "key press," are issued when the user interacts with a widget through the mouse or keyboard. Event classes, used to represent the event, contain detailed information about what has happened. For example, when the user selects an item in a list, an event is created, capturing the fact that a "selection" occurred. The event is delivered to the application via a listener.

A listener is an instance of a class that implements one or more agreed-upon methods whose signatures are captured by an interface. Listener methods always take an instance of an event class as an argument. When something interesting occurs in a widget, the listener method is invoked with an appropriate event.

Most widgets track sequences of events and redraw based on them, sometimes issuing a higher-level event to indicate a state change. For example, a button may track "mouse press," "move," and "release" in order to issue a "selection" event when the mouse is released inside the button.

Some widget methods generate events. For example, when you call setFocus() on a control, "focus" events are issued. The rules governing which methods cause events and which do not are largely historical, based on the behavior of the Windows and X/Motif operating systems. In order to be able to write portable applications, these rules have been standardized across platforms.

SWT has two kinds of listeners: untyped and typed.

1.3.1 Untyped Listeners

Untyped listeners provide a simple, generic, low-level mechanism to handle any type of event. There are only two Java types involved: a single generic interface called Listener and a single event class called Event. Untyped listeners are added using the method addListener().

addListener(int event, Listener listener) Adds the listener to the collection of listeners that will be notified when an event of the given type occurs. When the event occurs in the widget, the listener is notified by calling its handleEvent() method.

The type argument specifies the event you are interested in receiving. To help distinguish them from all the other SWT constants, type arguments are mixed upper- and lowercase by convention. All other constants in SWT are uppercase. The following code fragment uses addListener() to add a listener for SWT.Dispose.






widget.addListener(SWT.Dispose, new Listener() {

    public void handleEvent(Event event) {

        // widget was disposed

    }

});


When multiple listeners are added, they are called in the order they were added. This gives the first listener the opportunity to process the event and possibly filter the data before the remaining listeners are notified (see Event Filters in the chapter Display). Adding the same instance of a listener multiple times is supported, causing it to be invoked once for each time it was added.[12]

[12] We can't think of any reason you would want to add the same listener multiple times but there is no restriction to stop you from doing this.

It is also possible to remove listeners using removeListener().

removeListener(int type, Listener listener) Removes the listener from the collection of listeners that will be notified when an event of the given type occurs.

In order for a listener to be removed, you must supply the exact instance of the listener that was added. If the same listener instance is added multiple times, it must be removed the same number of times it was added to remove it from the listener collection completely.

Generally speaking, removing listeners is unnecessary. Listeners are garbage collected when a control is disposed of, provided that there are no other references to the listener in the application program.

Application code can send events using notifyListeners().

notifyListeners(int type, Event event) Sets the type of the event to the given type and calls Listener.handleEvent() for each listener in the collection of listeners.

An important point to note is that notifyListeners() does not cause the corresponding operating system event to occur. For example, calling notifyListeners() with SWT.MouseDown on a button will not cause the button to appear to be pressed. Also, notifyListeners() does not ensure that the appropriate fields for the event have been correctly initialized for the given type of event. You can use notifyListeners() to invoke listeners that you define but it is probably easier simply to put the code in a helper method.

Class Event has a number of fields that are applicable only for a subset of the event types. These fields are discussed as each type of event is described. Table 1.1 shows the fields that are valid for all event types.

Table 1.1. Public Fields in Class Event That Are Applicable to All Untyped Events

Field

Description

display

the Display on which the event occurred

widget

the Widget that issued the event

type

the event type


Table 1.2 shows the type constants that describe all of the untyped events that SWT implements. More details are available in the descriptions of the individual widgets.

Table 1.2. Untyped Events

Event Type Constant

Description

SWT.KeyDown

A key was pressed

SWT.KeyUp

A key was released

SWT.MouseDown

A mouse button was pressed

SWT.MouseUp

A mouse button was released

SWT.MouseMove

The mouse was moved

SWT.MouseEnter

The mouse entered the client area of the control

SWT.MouseHover

The mouse lingered over a control

SWT.MouseExit

The mouse exited the client area of the control

SWT.MouseDoubleClick

A mouse button was pressed twice

SWT.Paint

A control was asked to draw

SWT.Move

The position of the control was changed

SWT.Resize

The size of the client area of the control changed

SWT.Dispose

The widget was disposed

SWT.Selection

A selection occurred in the widget

SWT.DefaultSelection

The default selection occurred in the widget

SWT.FocusIn

Keyboard focus was given to the control

SWT.FocusOut

The control lost keyboard focus

SWT.Expand

A tree item was expanded

SWT.Collapse

A tree item was collapsed

SWT.Iconify

The shell was minimized

SWT.Deiconify

The shell is no longer minimized

SWT.Close

The shell is being closed

SWT.Show

The widget is becoming visible

SWT.Hide

The widget is being hidden

SWT.Modify

Text has changed in the control

SWT.Verify

Text is to be validated in the control

SWT.Activate

The control is being activated

SWT.Deactivate

The control is being deactivated

SWT.Help

The user requested help for the widget

SWT.DragDetect

A drag-and-drop user action occurred

SWT.MenuDetect

The user requested a context menu

SWT.Arm

The menu item is drawn in the armed state

SWT.Traverse

A keyboard navigation event occurred

SWT.HardKeyDown

A hardware button was pressed (handhelds)

SWT.HardKeyUp

A hardware button was released (handhelds)


If you are writing your own widget, you may want to use notifyListeners() to support the built-in untyped events in SWT since this allows your widget to behave like the native widgets with respect to the mapping between untyped and typed listeners. However, for events that are particular to your widget, you will also typically implement typed listeners.

1.3.2 Typed Listeners

A typed listener follows the standard JavaBeans listener pattern. Typed listeners and their corresponding event classes are found in the package org.eclipse.swt.events. For example, to listen for a dispose event on a widget, application code would use addDisposeListener().

addDisposeListener(DisposeListener listener) Adds the listener to the collection of listeners that will be notified when a widget is disposed. When the widget is disposed, the listener is notified by calling its widgetDisposed() method.

The following code fragment listens for a dispose event on a widget.






widget.addDisposeListener(new DisposeListener() {

    public void widgetDisposed(DisposeEvent event) {

        // widget was disposed

    }

});


DisposeListener is an interface. If there is more than one method defined by the listener, SWT provides an adapter class that contains no-op implementations of the methods.[13] For example, the interface SelectionListener has two methods, widgetSelected() and widgetDefaultSelected(), that take SelectionEvents as arguments. As a result, the class SelectionAdapter is provided that provides no-op implementations for each method.

[13] Adapter classes are provided for convenience and to adhere to JavaBeans listener conventions.

Typed listeners are removed using the corresponding remove method for the listener. For example, a listener for a dispose event is removed using removeDisposeListener().

removeDisposeListener(DisposeListener listener) Removes the listener from the collection of listeners that will be notified when the widget is disposed.

Table 1.3 shows all of the typed events that SWT implements. These are described in more detail in the descriptions of the individual widgets.

Table 1.3. Typed Events

Event

Listener

Methods

Untyped Event

ArmEvent

ArmListener

widgetArmed(ArmEvent)

SWT.Arm

ControlEvent

ControlListener (and ControlAdapter)

controlMoved(ControlEvent)

controlResized(ControlEvent)

SWT.Move

SWT.Resize

DisposeEvent

DisposeListener

widgetDisposed(DisposeEvent)

SWT.Dispose

FocusEvent

FocusListener (and FocusAdapter)

focusGained(FocusEvent)

focusLost(FocusEvent)

SWT.FocusIn

SWT.FocusOut

HelpEvent

HelpListener

helpRequested(HelpEvent)

SWT.Help

KeyEvent

KeyListener (and KeyAdapter)

keyPressed(KeyEvent)

keyReleased(KeyEvent)

SWT.KeyPressed

SWT.KeyReleased

MenuEvent

MenuListener (and MenuAdapter)

menuHidden(MenuEvent)

menuShown(MenuEvent)

SWT.Hide

SWT.Show

ModifyEvent

ModifyListener

modifyText(ModifyEvent)

SWT.Modify

MouseEvent

MouseListener (and MouseAdapter)

mouseDoubleClick(MouseEvent)

mouseDown(MouseEvent)

mouseUp(MouseEvent)

SWT.MouseDoubleClick

SWT.MouseDown

SWT.MouseUp

MouseEvent

MouseMoveListener

mouseMove(MouseEvent)

SWT.MouseMove

MouseEvent

MouseTrackListener (and MouseTrackAdapter)

mouseEnter(MouseEvent)

mouseExit(MouseEvent)

mouseHover(MouseEvent)

SWT.MouseEnter

SWT.MouseExit

SWT.MouseHover

PaintEvent

PaintListener

paintControl(PaintEvent)

SWT.Paint

SelectionEvent

SelectionListener (and SelectionAdapter)

widgetDefaultSelected(SelectionEvent)

widgetSelected(SelectionEvent)

SWT.DefaultSelection

SWT.Selection

ShellEvent

ShellListener (and ShellAdapter)

shellActivated(ShellEvent)

shellClosed(ShellEvent)

shellDeactivated(ShellEvent)

shellDeiconified(ShellEvent)

shellIconified(ShellEvent)

SWT.Activate

SWT.Close

SWT.Deactivate

SWT.Deiconify

SWT.Iconify

TraverseEvent

TraverseListener

keyTraversed(TraverseEvent)

SWT.Traverse

TreeEvent

TreeListener (and TreeAdapter)

treeCollapsed(TreeEvent)

treeExpanded(TreeEvent)

SWT.Collapse

SWT.Expand

VerifyEvent

VerifyListener

verifyText(VerifyEvent)

SWT.Verify


1.3.3 Why Are There Two Listener Mechanisms?

In early versions of SWT, there were only untyped listeners. After considerable discussion between the Eclipse implementers, the SWT user community, and the developers, it was decided to include a more "JavaBeans-like" listener mechanism. It was felt that this would ease the transition to SWT for developers who were already familiar with AWT/Swing. The untyped listeners remain as the implementation mechanism for event handling in SWT. The typed listeners are defined in terms of them.

We recommend that SWT applications always be implemented in terms of the typed listener mechanism, although this is largely based on the more familiar pattern they represent. Because of the simplicity of the untyped mechanism and our closeness to the implementation, we tend to use it in many of the small examples we write. To see a clear example of the typed mechanism in action, take a look at the FileExplorer example in the Applications part of the book.

Effectively, the trade-off between the two listener models is one of space versus ease of use and adherence to a standard pattern. Using untyped listeners, it is possible to minimize the number of classes and methods used to listen for events. The same listener can be used to listen for many different event types. For example, the following code fragment listens for dispose as well as mouse events.






Listener listener = new Listener() {

    public void handleEvent(Event event) {

        switch (event.type) {

            case SWT.Dispose: break;

            case SWT.MouseDown: break;

            case SWT.MouseUp: break;

            case SWT.MouseMove: break;

        }

        System.out.println("Something happened.");

    }

};

shell.addListener(SWT.Dispose, listener);

shell.addListener(SWT.MouseDown, listener);

shell.addListener(SWT.MouseUp, listener);

shell.addListener(SWT.MouseMove, listener);


In practice, unless space usage is the overwhelming constraint, we expect that most programmers will use the typed listener mechanism.[14] Note that typed events have very specific listener APIs, whereas the untyped events have only handleEvent(). Using untyped events can lead to switch logic that is more complicated. Refer to Table 1.3 to see the mapping between typed and untyped events.

[14] All of the typed listeners provided by the native widgets in SWT are found in the package org.eclipse.swt.events. When space is extremely limited, this package and all of the corresponding addXXXListener() and removeXXXListener() methods in org.eclipse.swt.widgets can be safely removed.

1.3.4 Widget Events

SWT.Dispose (DisposeEvent)

Table 1.4 shows the dispose events that are provided by SWT.

Table 1.4. Dispose Events

Untyped Event

Description

SWT.Dispose

The widget was disposed

Typed Event

Listener

Methods

DisposeEvent

DisposeListener

widgetDisposed(DisposeEvent)


The SWT.Dispose event (typed event DisposeEvent) is sent when a widget is disposed of. Dispose events contain meaningful values in only the display, widget, and type fields.

    Previous Section  < Day Day Up >  Next Section