Events in JDK 1.1 : Java Glossary


Events in Java 1.1+
Introduction Actions Event vs. AWTEvent
Overview Consume Keystroke Events
The Cast Anatomy Keystroke Names
Conception Cremation Synthetic Events
Event Loop TABLE JDK 1.0
Creation Censoring Java 1.3+
Enqueuing Activating Repaint
Dispatching textValueChanged Learning More
Classification Missing Events Credits
Notifying Mouse Events Summary
Listeners Mouse Buttons Links

Introduction

In Java version 1.6 or later, Events are handled quite differently from JDK 1.0.2. This essay will follow a single Event from creationto cremation to give you an idea of how it all fits together. For details, and practical coding concerns, I suggest you read some other essays on Events such as Richard Baldwin’s instructional essays. I have written a similar essay for the older JDK (Java Development Kit) 1.0.2 Events.

I’m a guy who can’t use a tool until I have some model of how it works under the hood. If you are that way, you will like this essay. If you are the kind of programmer who simply wants to use the tool without any interest of how it works inside, all you need pay attention to in this essay is how EventListeners work.

Overview

Events are: Events are hard to understand because there are three different mechanism meshing.
  1. A callback delegate mechanisms so that Sun-written Components can call code you write when something interesting happens via the various listener interfaces. The listener mechanism is more complex than your usual callback. The callee, remembers multiple callers, then calls them back later, asynchronously when something interesting happens.
  2. A queuing mechanism to procrastinate work. Basically it is a to-do list. High priority work gets done first. If the system gets behind, it can skip some of the validates or repaints since the later ones will cover the earlier ones. The queue mechanism also coordinates many Threads all making changes to the screen at once. They put their requests into a queue and a single Thread does all the work without any worries of other Threads interfering.
  3. It is also an Event delivery mechanism so that an Event (notification of something interesting happening) can be easily forwarded to other possibly interested parties.
Instead of Events percolating up to parents as they did in JDK 1.0.2, any object or component can register itself as a listener, interested in hearing about a type of Events originating in some other component. When the Event arises, the source component processes the Event by dispatching it to each of the registered listeners. Dispatching is synchronous, i.e. the listener handler routines are called directly while the calling dispatcher waits for the handler to complete. According to the specification, the listeners may be informed in any order, but the usual implementation is a queue, with listeners informed in the same order they were added. If you want to be absolutely sure of a fixed order of handling listeners, make your own chain and pass the Event between them. listeners pretty much only hear Events they are interested in. They are not responsible for passing the Event on to anyone else.

The new Event model gives you three places to hook in your code to process Events.

  1. via listeners. This is by far the most common way and the easiest to set up. The listener can be any object, e.g. the enclosing frame, the component itself, a non-GUI code object, a mom object to mother a set of components. A given listener can service several sources, and a given source can notify several target listeners. listener methods have names like actionPerformed, windowClosed, mouseMoved. Listeners are often implemented with Adapter classes so you don’t have to write dummy methods for Events you are not interested in. Adapter classes have names like: java.awt.event.FocusAdapter, KeyAdapter and WindowAdapter. Note, there is no such thing as ActionAdapter since it has only one method. Often you use inner classes or anonymous classes to handle fielding Events by extending an adapter class. Be very careful in extending adapter classes to get your method names and signatures exactly right. Otherwise you won’t override the corresponding dummy method, and your code won’t ever be executed, leaving you wondering where all the Events went.
  2. via processEvent which receives all raw Events for the component. It does not see Events coming in via listeners. If you override it, be sure to call super.processEvent to ensure all the finer Event handlers, like processKeyEvent, ProcessActionEvent etc. also get called and the listeners alerted. If you attempt to restrict the Events coming to processEvent with enableEvents(mask), if there are listeners registered for Events not in the mask, those Event classes will arrive anyway.
  3. via processXXXX(SomeEventClass e), e.g. processActionEvent, processItemEvent. Every raw Event for the component of that class comes through here. It does not see Events coming in via listeners. Be sure to call super.processXXXX to ensure the listeners are alerted.
A component might quite reasonably register itself as a listener for Events arising in itself or for Events arising from the associated native GUI. There is another deprecated technique to process Events arising in itself. A component could override its processEvent routine, do some action, then call super.processEvent (which would inform all the listeners), then do some other action.

The Cast of Players

Methods for registering a target as a listener of Events arising in some source include: source.addActionListener(target), addAdjustmentListener, addComponentListener, addContainerListener, addFocusListener, addItemListener, addKeyListener, addMouseListener, addMouseMotionListener, addPropertyChangeListener, addTextListener, addVetoableChangeListener, addWindowListener… Normally you would invoke these methods but not override them.

The AWT informs the list of registered listeners that an Event has occurred by calling the generic source.processEvent which in turn calls the more specific Event handler: source.processActionEvent, processAdjustmentEvent, processComponentEvent, processContainerEvent, processItemEvent, processKeyEvent, processMouseEvent, processMouseMotionEvent, firePropertyChange, processTextEvent, fireVetoableChange, processWindowEvent… These routines would in turn use the AWTEventMulticaster to inform all the listeners and invoke their actionPerformed, keyPressed, windowOpened etc. methods in turn. These processXXX routines typically work by calling the relevant dispatching routines on the listener targets. It is unlikely you will ever deal with these methods directly.

Your listener object must implement one or more interfaces such as: ActionListener, ComponentListener, ContainerListener, FocusListener, KeyListener, ItemListener, MouseListener, MouseMotionListener, TextListener, WindowListener…

The easiest way to implement those interfaces is to extend one of the related adapter classes. The adapter classes provide dummy methods to deal with the subcategories of Events that are of no interest to you. ComponentAdapter, ContainerAdapter, FocusAdapter, KeyListener, ItemAdapter, MouseAdapter, MouseMotionAdapter, TextAdapter, WindowAdapter…

The Event is dispatched to each target Listener by invoking its listening method. These have names like: target.actionPerformed, adjustmentValueChanged, componentHidden, componentMoved, componentResized, componentShown, componentAdded, componentRemoved, focusGained, focusLost, itemStateChanged, keyPressed, keyReleased, keyTyped, mouseClicked, mouseEntered, mouseExited, mousePressed, mouseReleased, textValueChanged, windowActivated, windowClosed, windowClosing, windowDeactivated, windowDecionified, WindowIconified, windowOpened… You need to write custom versions of these routines.

If there is a listener for an Event type registered, then Events from the GUI for that Event type will be delivered to that component’s processEvent. The component can control which additional types are delivered to processEvent by calling enableEvents with a mask. This way events that no one is interested in are not even delivered to processEvent. It is unlikely you will be directly involved with enableEvents.

A key point to understand is that a component has two kinds of acceptor routines for Events.

  1. The generic processEvent routine primarily accepts Events indirectly coming from the native GUI. Application programmers do not normally use these methods.
  2. The listener methods, e.g. actionPerformed, accept Events from other components. This is the main tool for application programmers to deal with Events. Component writers can also use the EventListener interface by registering a custom component as a listener to Events arising in itself.

The Life Cycle of An Event

Where do Events Come From Daddy?

You synthesize an AWTEvent and post to the SystemEventQueue for
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent( Event e );
In this Alice in Wonderland world, you set the source field of the Event to the component or peer where you want the Event delivered. Later, when the source delivers the Event to the various listeners, the term source for this field will make more sense. A potentially separate thread will service the queue asynchronously. When the Event percolates to the head of the queue, the dispatcher will call event.getSource().processEvent(event);

Most Events arise in the native GUI. They can enter the Java system in one of two ways:

  1. Notification of interesting happenings in the GUI arrive as a single stream of messages mentioning native GUI components. This is the traditional native GUI Event loop handled by hidden code, that calls getMessage() in a loop. The AWT uses a hash table to convert references to native GUI components into the corresponding Java components and peers, and composes corresponding Java Events and enqueues them in the SystemEventQueue.
  2. Java peer components generate Events based on information they glean from the native GUI. These too are enqueued in the SystemEventQueue.
Lightweight components generate Events and post them directly to themselves, without going through the SystemEventQueue.

Where is the Event Loop?

People who cut their teeth in the Windows or Mac native low level GUI API are used to writing application-specific code to handle dispatching using an Event processing loop. The AWT handles this all automatically and invisibly in EventDispatchThread.run. It reads the stream of native GUI Event messages, and translates them, creating Java Events, which it puts into the SystemEventQueue. The thread that processes Events, when it finishing processing one Event, goes and picks up another Event off the head of the Event queue to dispatch. This is the very thread that executes most of your application code.

The loop that processes Events does not even start until your main program has finished executing!! This Event loop code is not visible to the application programmer.

You might naïvely imagine there is some sort of mail delivery service that delivers Events to their destinations. It is much simpler than that. The Event object contains a reference to the target object. To deliver/dispatch the Event, all the system has to do is call a method on that reference. It is a little more complicated than that since an Event handler may call a chain of Event handlers. The target object is confusingly called the source. It makes sense if you consider that Events usually come back to the same object that generated them. From the point of view of listeners, the Events appear to come from these source objects.

You can think of Events as a way of enqueing work to be done later, usually by other objects.

Creation

Consider what happens behind the scenes when the user clicks an OK button on the screen. The underlying native GUI notices the mouse click.
It could then work one of two ways:
  1. The native GUI indirectly notifies the Java Button peer object which creates a new Event using the ActionEvent constructor.
  2. The GUI creates a native format message that a button has been clicked. Hidden code in the AWT reads this stream of messages and translates this one into a new Event using the ActionEvent constructor. It has a Hashtable to convert references to native peer components to the corresponding Java components.
  3. event source
    A Java component closely associated with this event, namely myButton. At first this field acts as the destination for the Event. Later it informs listeners where the Event came from.
    event id
    the type of event, in this case ActionEvent.ACTION_PERFORMED.
    event command
    the command string for this action event. In this case it would be the string OK.
    event modifiers
    the modifiers held down during this click, e.g. CTRL_MASK if the Ctrl key is held down

Enqueuing

The
EventQueue q = Toolkit.getDefaultToolkit().getSystemEventQueue();
Now it can enqueue the Event for delivery to the source ( myButton) with the system’s postEvent method. We don’t use
q.postEvent( e );
The Event hibernates in the queue waiting its turn to be dispatched. postEvent will return immediately. It won’t wait until the new Event has been delivered.

Dispatching

There is a single system thread that grabs the next item off the queue and dispatches it. You can see the code for it in EventDispatchThread.run When all the processing for that Event is complete, it gets the next Event. No other Event processing, not even a mouse move, can happen until the previous Event has been processed. I repeat, only one Event is processed at a time.

Having said that, this single-thread behaviour is not part of the specification. There are some JVMs (Java Virtual Machines) where you have several threads processing Events simultaneously.

It looks at the source field in the Event object, and delivers the Event to that source object.

First it checks the java.awt.Component.eventMask to be sure the myButton component is willing to accept that flavour of Event.

The button could conceivably have used java.awt.Component.disableEvents to filter out Events such as ours. disableEvents takes bit masks for groups of Events such as java.awt.AWTEvent.MOUSE_MOTION_EVENT_MASK. You cannot feed it individual Events such as java.awt.event.MouseEvent.MOUSE_ENTERED, because these constants are not in bit mask form. One my main bitches about Java is this bit map / enumeration ambiguity.

It also checks if there are listeners for our type of Event. If there are, even if our Event type is blocked, our Event will still be delivered.

It delivers the Event to the button component by calling myButton’s generic processEvent Event handler:

myButton.processEvent( e );
or
e.getSource().processEvent( e );
This dispatching mechanism is efficient because it does not require any sort of table lookup or nested switch statements.

Classification

processEvent could in theory do some special processing on the Event, but usually all it does is classify the Event and call a more specialised Event handler such as: processActionEvent. (If you override processEvent, make sure you call super.processEvent to ensure the standard Event processing also occurs.) Had we been processing a mouse Event, we would have called processMouseEvent instead.

Notifying Listeners

A long time ago, before this Event was born, parties interested in this type of Event registered their interest by using myButton. addActionListener(myListener). It is important to remember that addXXXXListener methods are implemented by the sources, not the listeners. In theory, the addXXXXListener methods could be invoked by the source or the listener, but usually they are invoked by a third party, usually an enclosing frame.

Raw Events arrive via processEvent. They are classified and redirected to more specialised Event processors like processActionEvent.

processActionEvent can further classify the incoming Events and can do whatever special processing it wants. Then it notifies any listeners, one after the other. (If you override processActionEvent, make sure you call super.processActionEvent to ensure the listeners are notified.)

Each listener effectively gets a fresh cloned copy of the original Event. Unfortunately, this wastes cpu cycles and creates a ton of run time garbage. The intent is to make Events effectively read-only and to render harmless any malicious component that stored a reference to an Event. Once an Event enters Component.processKeyEvent, it isn’t replicated anymore so presumably some of its fields could be modified and used for communication. Ideally Event objects would be read-only and recyclable.

There is no guarantee that the listeners will be notified in any particular order, however they will be notified one at a time, never in parallel.

To notify each registered listener, the speaker’s processActionEvent calls each listener’s actionPerformed(e) method by chasing the AWTEventMultiCaster listener chain.

AWTEventMulticaster contains generic code that most components use for implementing addXXXListener and the notification of listeners. Component has various add/remove listener methods that use AWTEventMulticaster that all Components inherit.

If we had been processing a mouse motion, we would have called the listener’s mouseMoved method instead. processActionEvent methods are designed to be called by processEvent; methods like actionPerformed and mouseMoved are part of listener interfaces. Most application coding uses only listeners. Only if you were inventing a new sort of component would you get involved with processEvent and processActionEvent.

What Are Listeners?

A Listener is any object that:
  1. implements one of the EventListener interfaces such as ActionListener, e. g. An ActionListener must implement an actionPerformed method to be called when an Action Event occurs.
  2. Has hooked itself (or been hooked by a third party) onto one or more Event-generating components with a method such as addActionListener.
Listeners are written mostly by application programmers to field notifications of interesting things that happen to Sun-written widgets such as JButtons.

A listener might be a component, an ordinary object, a special Mom object to mother a set of components or an anonymous object created from an anonymous class to simply provide a hook to some other routine.

A listener might be created by extending one of the adapter shortcut classes. The adapter classes give you some dummy classes to start with in defining a listener where you only want to handle a few types of Event.

A component may even register itself as a listener for Events originating it itself. This is the preferred method for application programmers since there is less possibility of mucking up standard Event processing.

A listener can field Events from many different sources. Similarly a source may notify many different listeners. Alternatively you could have a separate listener object for every source, or anything in between.

Components like JButtons implement interfaces like ItemSelectable. The provide methods like addItemListener so that classes that implement the ItemListener interface can arrange to be notified of interesting events in the button, such as it being pressed by first hooking themselves up through JButton.addItemListener.

The JButton uses EventListenList to maintain the list of interested listeners. When something interesting happen its calls fireActionPerformed which calls each of the actionPerformed methods of the register listeners. Even though an event gets passed to the actionPerformed method, the listener mechanism does not necessarily mean the event spent any time in a queue. It could be created and passed immediately to the listeners when the interesting event happened.

You could even use the listener mechanism in your own code, for both the notifier and listener end, for situations where it is hard to keep track of who should notify whom when some interesting thing happens. You don’t need to modify the callee’s code to add more interested parties. You don’t need an event queue.

You can also set up a listener to monitor all the events. You might use this to monitor keyboard or mouse activity for a timeout to shutdown after a period of inactivity.

Listener Actions

What does the listener do when it’s actionPerformed (or other mouseMoved etc…) method is called? It may classify the incoming Event based on source, id or class (via instanceof). Then it would perform some action, do a calculation, change the look of the screen, delete a file… If it wants, it can use the consume() method to mark the Event consumedto discourage further processing on it.

It had better be quick! The entire system is at a standstill, unable to process any more Events until your listener completes its action. If the action is going to take more than a few milliseconds you should either:

In a similar vein, if it is very important that some action not start until after the physical paint is finished, the simplest way to arrange that is to have paint kick it off, perhaps by examining some flag to see if kickoff is necessary.

How Does consume() Work?

I have not found a precise definition of what is supposed to happen to a consumed Event. By experiment, I discovered it seems to stop further processing by the base classes of the current component. It does not seem to stop notification of others listeners. I found for example that in TextField, consuming a keystroke Event would prevent it being displayed. However, this does not work with the KL group JCTextField or the Swing JTextField. There you must override processKeyEvent.

After all the listeners have been called, the Event is checked to see if it has been consumed. If so, then it is not passed onto the next stage. For e.g. KeyEvents for a TextArea, this means that it is not passed back to the peer, and so does not reach the underlying window/widget, and so does not appear.

consume() in KeyListeners is effectively broken in Swing 0.7 since it is ignored. It looks like the Event is drawn in JTextArea before being given to the listeners.

For TextFields, you can change the value of the keystroke in the Event in a KeyListener before passing it on, e.g. convert it to lower or upper case. However under Motif, converting to lower case is broken, and the entire technique is broken for Swing. You would have to trap processKeyEvent instead. In a TextField in the AWT (Advanced Windowing Toolkit), you get the Event before the character has been painted on the screen. Therefore if you do a getText or setText in your Event handler, very likely will thoroughly confuse the AWT. The AWT was not designed to do anything useful, just to look good on paper. To save your sanity, it is perhaps best to look on the AWT as a mystery/adventure game. Your task is to figure out by experiment what the methods do. Their names give you the barest of clues. You then McGuyver-like must cobble the odd bits together to create something practical.

How Do You Compose a Listener?

Java version 1.1 added inner classes and anonymous classes to make it easier to hook up listener code. Here is code that could appear in the middle of a frame initialisation method that:
  1. defines a new anonymous class that extends the WindowAdapter listener.
  2. defines a method in that class to deal with window closing Events.
  3. allocates an object of that class.
  4. hooks that object up as a listener to the current frame component.
  5. throws away the reference to the class. (The object won’t die since it is on the list of listeners.)

Cremation

The various listeners eventually complete their work and return to actionPerformed. The return stack unwinds: actionPerformed returns. processActionEvent returns. processEvent returns. We are now back at system the code that dispatches Events from the queue. Our Event is forgotten and the next Event takes the stage. With no more references to our old Event, garbage collection soon recycles the RAM (Random Access Memory) that the Event occupied.

Table of Event Classes and Methods

Now we need to generalise from those specific examples.

Instead of creating an ActionEvent with id ActionEvent.ACTION_PERFORMED, that is dispatched to processEvent, then passed on to processActionEvent, then passed on to an ActionListener (that registered its interest via addActionListener) via its actionPerformed method, there are many other possibilities you can generate from the following table:

When Event Class id Specific
Event
Handler
Listener
Interface
Listener
Notification
Method
Listener
registration
Adapter shortcut Typical Components
Button clicked, MenuItem clicked, but not Choice selected. ActionEvent ACTION_PERFORMED processActionEvent ActionListener actionPerformed addActionListener   Button, JButton, MenuItem, JMenuItem
Slider moved AdjustmentEvent ADJUSTMENT_VALUE_CHANGED processAdjustmentEvent AdjustmentListener
ScrollPane
adjustmentValueChanged addAdjustmentListener   JSlider
Component hidden, moved, resized, revealed. ComponentEvent COMPONENT_HIDDEN
COMPONENT_MOVED
COMPONENT_RESIZED
COMPONENT_SHOWN
processComponentEvent ComponentListener componentHidden
componentMoved
componentResized
componentShown
addComponentListener ComponentAdapter Component
something added or removed to this container. ContainerEvent COMPONENT_ADDED
COMPONENT_REMOVED
processContainerEvent ContainerListener componentAdded
componentRemoved
addContainerListener ContainerAdapter Container, Panel, Jpanel, Frame, JFrame
Focus changed, either by mouse or tab FocusEvent FOCUS_GAINED
FOCUS_LOST
processFocusEvent FocusListener focusGained
focusLost
addFocusListener FocusAdapter Component
Ancestor added or removed HierarchyEvent HIERARCHY_CHANGED processHierarchyEvent HierarchyListener hierarchyChanged addHierarchyListener Component
Ancestor moved or resized HierarchyBoundsListener ANCESTOR_MOVED ANCESTOR_RESIZED processsHierarchyBoundsEvent HierarchyBoundsListener ancestorMoved
ancestorResized
addHierarchyBoundsListener Component
user keyed something into a text box InputMethodEvent INPUT_METHOD_TEXT_CHANGED
CARET_POSITION_CHANGED
processInputMethodEvent InputMethodListener inputMethodTextChanged
caretPositionChanged
addInputMethodListener   Component
user selected a different Choice ItemEvent DESELECTED
ITEM_STATE_CHANGED
SELECTED
processItemEvent ItemListener itemStateChanged addItemListener   Choice, JComboBox
keystroke KeyEvent KEY_PRESSED (e.g. shift, F1)
KEY_RELEASED
KEY_TYPED (e.g. a A)
processKeyEvent KeyListener keyPressed
keyReleased
keyTyped
addKeyListener KeyAdapter Panel, JPanel, Frame, JFrame
not Button, JButton, TextArea, JTextArea, Choice, ComboBox, Checkbox, JCheckbox
Mouse clicked, entered or exited the region. See also ActionEvent and Item event. MouseEvent MOUSE_CLICKED
MOUSE_ENTERED
MOUSE_EXITED
MOUSE_PRESSED
MOUSE_RELEASED
processMouseEvent MouseListener mouseClicked
mouseEntered
mouseExited
mousePressed
mouseReleased
addMouseListener MouseAdapter Component, Canvas, Panel, JPanel,
not Button, JButton, TextArea, JTextArea, Choice, ComboBox, Checkbox, JCheckbox
Mouse moved. You normally don’t want to track these since there are so many of them. MouseMotionEvent MOUSE_DRAGGED
MOUSE_MOVED
processMouseMotionEvent MouseMotionListener mouseDragged
mouseMoved
addMouseMotionListener MouseMotionAdapter Component, Canvas, Panel, JPanel,
not Button, JButton, TextArea, JTextArea, Choice, ComboBox, Checkbox, JCheckbox
Mousewheel moved. MouseWheelEvent   processMouseWheelEvent MouseWheelListener mouseWheelMoved addMouseWheelListener Component
Canvas
JPanel
repaint PaintEvent PAINT
UPDATE
paint
update
        Component
value in a TextField changed. TextEvent TEXT_VALUE_CHANGED processTextEvent TextListener textValueChanged addTextListener   TextField, TextArea, JTextField, JTextArea
Window state change WindowEvent WINDOW_ACTIVATED
WINDOW_CLOSED
WINDOW_CLOSING
WINDOW_DEACTIVATED
WINDOW_DEICONIFIED
WINDOW_ICONIFIED
WINDOW_OPENED
processWindowEvent WindowListener windowActivated
windowClosed
windowClosing
windowDeactivated
windowDecionified
WindowIconified
windowOpened
addWindowListener WindowAdapter Frame, JFrame, Window, JWindow, Dialog, JDialog
For a complete list of the various Listener interfaces, and methods see the JDK API/Package-java.awt.event.html if you want to study the whole java.awt.event package.

Censoring or Remapping Keystrokes

Let us say you wanted to write your own version of TextField-like component that disallowed certain keystrokes, or that processed certain keystrokes specially. You may have tried the easy Listener/consume() method and discovered it did not work for your base component. Here is If you want the underlying base class not to see the Event, you consume it in one of your custom filter routines such as unicodeKeyPressed(e), and that suppresses the call to super.processKeyEvent. Something to baffle you. Hitting the Enter key under NT generates two keystrokes a \r and a \n. On other platforms you get just a \n. Best just to look for VK_ENTER.

In Swing you can use the Keymap and KeyStroke classes to control the actions of various keystrokes.

Activating

To activate your Listener, you need to create a callback delegate Listener object, and pass it to the Component. Then when something interesting happens, it can call one of the methods you wrote (to its interface specifications), perhaps indirectly via the Event queue.

Styles of Activating

There are several styles for activating:
  1. compact

    You do it all in one very complicated line, where you define an anonymous class, create an instance of it and feed it to the addListener method. The puts everything in one place. The code is an unreadable forest of parentheses braces and semicolons. They limit you to one component per listener. They generate one extra inner class per use. They don’t have to deal with the problem of figuring out which component the incoming event to the listener is relevant too. There is only one possibility. Java beautifiers tend to over-indent this style. Inner classes get total and easy access to all the mother class’s fields. The examples that follow are all of this style.
  2. anonymous class reference

    You create a reference to an anonymous inner class object then in a separate step, feed that to the addListener method. I prefer this to (1) because it is easier to proofread and SlickEdit beautifier renders it without excessive indentation. You have the option of reusing a Listener on several components. You can also collect all your listener logic in one place separate from the GUI (Graphic User Interface) logic which makes it easier to maintain. This is the style I most commonly use personally.
  3. named inner class reference

    Like (2), but you name the inner classes. Perhaps a little easier for novices to understand.
  4. named free standing classes

    like (3) but with ordinary classes that implement the Listener interfaces. They don’t have easy access to the parent class variable. You can use designs where the mother class itself implements the Listener interface, or where the Listener classes have additional functionality. The Listener classes can have parameters in their constructors, which anonymous inner classes cannot. This is the most flexible approach, but also requires the most typing.
  5. Stomp Style

    These are mechanically generated. One master hookListeners method calls a separate method to hook up each component. Those methods in turn build an anonymous listener and link it to the widget. On activation they call one line of code, which is yet another method that actually does the work. It is verbose, but easy to proofread because the important stuff is separated from the bubblegum. Here is
I would be happy to share my Stomp cookie cutter classes for you.

Activating a Button

Hooking up some code to be executed when a button is hit is very similar to the earlier WindowClosing example. There is no such thing as the ActionAdapter class, so

Activating a FocusListener

Activating a KeyListener

Activating a Choice or JCheckbox ItemListener

JMenuItems

Just a few simple menus will explode into gobs of code if you provide an anonymous ActionListener for each JMenuItem. Instead, use a common ActionListener for all JMenuItems or all JMenuItems in a JMenu. Give each JMenuItem a one-letter setActionCommand string. In your ActionListener, extract the command letter with getActionCommand().charAt(0) and use it to index a switch to select the piece of code that needs to execute. Remember to add your ActionListener to every individual JMenuItem. Best look into Actions for hooking up your JButtons and JMenuItems if you have more than a handful.

TextListener.textValueChanged

This method receives an event any time the text value of the component changes including when you change it programmatically with setText! This can cause your program to go into heart fibrillation, if your event handler does any setTexts that in turn will trigger further Events in a Disney-style ping-pong-balls-on-the-mousetraps fission-style chain reaction. To add to the confusion, some versions of the JDK don’t do this.

Missing Events

The newsgroups are full of plaintive messages from newbies claiming the AWT is broken because their listeners are not receiving any Events. Here are some things to check:

Mouse Events

There are three different listeners for the mouse, MouseListener, MouseMotionListener and MouseWheelListener.

If you click the mouse, you will get three events which will show up at mousePressed, then mouseReleased then mouseClicked.

If you move the mouse onto your component you will first get an event at mouseEntered. If you move if off the component, you will get an event at mouseExited.

Every time you move the mouse even a tad, you will get an event at mouseMoved.

If you press a mouse button and drag you will get an event at mousePressed followed by multiple events at mouseDragged reporting the current drag location. When you let go of the button, you get an event at mouseReleased. You won’t get an event at mouseClicked

If you twirl the wheelmouse on a Component in a ScrollPane, you won’t see events at the Component’s mouseWheelmoved. Instead you will see events at mouseMoved, as if there were no ScrollPane and user had moved the mouse instead. Events are mouseMoved are about relative motion over the virtual panned Component in the ScrollPane.

Detecting Shift, Alt and Ctrl, Left and Right Mouse Buttons

When the user hits Shift, Alt or Ctrl (or a combination) in conjunction with some ordinary key, you can determine that by looking at the KeyEvent.getModifiers, masking with ORed combinations of inputEvent.SHIFT_MASK, ALT_MASK, CTRL_MASK and META_MASK, in your keyTyped listener.

You can detect the separate pressing of Shift, Alt or Ctrl at the keyPressed() listener, and the releasing at the keyReleased listener, by testing KeyEvent.getKeyCode() for a match with KeyEvent.VK_SHIFT, VK_CONTROL, VK_ALT and KeyEvent.VK_META.

With the advent of Java version 1.3, you can detect and set the state of the various CapsLock-like states with: public boolean getLockingKeyState(int keyCode) and public void setLockingKeyState(int keyCode, boolean on). Valid key codes are: VK_CAPS_LOCK, VK_NUM_LOCK, VK_SCROLL_LOCK, VK_KANA_LOCK.

Dealing with mouse clicks is similar. In your mouseClicked listener, MouseEvent.getModifiers() returns the state of all the modifier keys and mouse buttons when the event was fired. You can use this method to determine which mouse button was pressed (or newly released) when a mouse Event was fired. You mask the result with an ORed combination of InputEvent.ALT_MASK, BUTTON1_MASK, BUTTON2__MASK, BUTTON3_MASK, CTRL_MASK, META_MASK, and SHIFT_MASK. For example, the following expression is true if the right button was pressed:

The various combinations of ID, keyCode() and keyChar() in the KeyEvent are quite complicated.

getID() tells you the type of event, basically which listener was used. KeyCode() gets you a raw Keyboard code e.g. A. keyChar() gets you the cooked character e.g. a. See KeyListener in the Java glossary for more discussion.

I suggest downloading my little KeyPlay application. You can play with it, clicking the mouse and hitting keystrokes. A description of the Events generated is dumped to the console. With it, you can quickly learn about the ordering of Events, and the use of the fields. You will discover most JVMs work the same way, with the exception of Microsoft’s which is out in left field. Check out Oracle’s java.awt. Robot class for generating simulated keystrokes and mouse moves.

Keystroke Events

Whenever you hit a key on the keyboard, three events will show up at your KeyListener, first an event at keyPressed, then at keyTyped, then at keyReleased. If you hold a key down and it repeats, you will see that triple repeated over and over. If you hit the ctrl key and hold it down you will see repeated events at keyPressed and finally one at keyReleased when you let go. There is no event at keyTyped. When you hit Ctrl+C you see keyCode 03, ^C, ETX (End of Text) not the letter C. Java combines the keys for you. It is not your problem to track the ctrl or shift state and modify the meanings of other keystrokes.

Keystroke Names

You should write your code using these KeyChar and KeyCode names from java.awt.event.KeyEvent rather than hard-coding the numeric literals. These are the set available in JDK 1.6. The list has been gradually expanding with every new release. You may find some of these will not work is older JDKs (Java Development Kits). Most notably, they added VK_SEPARATOR to correct the spelling mistake in VK_SEPARATER.
Numeric Ordering
name hex decimal
VK_UNDEFINED 0x0000 0
VK_CANCEL 0x0003 3
VK_BACK_SPACE (\b) 0x0008 8
VK_TAB (\t) 0x0009 9
VK_ENTER (\n) 0x000a 10
VK_CLEAR 0x000c 12
VK_SHIFT 0x0010 16
VK_CONTROL 0x0011 17
VK_ALT 0x0012 18
VK_PAUSE 0x0013 19
VK_CAPS_LOCK 0x0014 20
VK_KANA 0x0015 21
VK_FINAL 0x0018 24
VK_KANJI 0x0019 25
VK_ESCAPE 0x001b 27
VK_CONVERT 0x001c 28
VK_NONCONVERT 0x001d 29
VK_ACCEPT 0x001e 30
VK_MODECHANGE 0x001f 31
VK_SPACE 0x0020 32
VK_PAGE_UP 0x0021 33
VK_PAGE_DOWN 0x0022 34
VK_END 0x0023 35
VK_HOME 0x0024 36
VK_LEFT 0x0025 37
VK_UP 0x0026 38
VK_RIGHT 0x0027 39
VK_DOWN 0x0028 40
VK_COMMA 0x002c 44
VK_MINUS 0x002d 45
VK_PERIOD 0x002e 46
VK_SLASH 0x002f 47
VK_0 0x0030 48
VK_1 0x0031 49
VK_2 0x0032 50
VK_3 0x0033 51
VK_4 0x0034 52
VK_5 0x0035 53
VK_6 0x0036 54
VK_7 0x0037 55
VK_8 0x0038 56
VK_9 0x0039 57
VK_SEMICOLON 0x003b 59
VK_EQUALS 0x003d 61
VK_A 0x0041 65
VK_B 0x0042 66
VK_C 0x0043 67
VK_D 0x0044 68
VK_E 0x0045 69
VK_F 0x0046 70
VK_G 0x0047 71
VK_H 0x0048 72
VK_I 0x0049 73
VK_J 0x004a 74
VK_K 0x004b 75
VK_L 0x004c 76
VK_M 0x004d 77
VK_N 0x004e 78
VK_O 0x004f 79
VK_P 0x0050 80
VK_Q 0x0051 81
VK_R 0x0052 82
VK_S 0x0053 83
VK_T 0x0054 84
VK_U 0x0055 85
VK_V 0x0056 86
VK_W 0x0057 87
VK_X 0x0058 88
VK_Y 0x0059 89
VK_Z 0x005a 90
VK_OPEN_BRACKET 0x005b 91
VK_BACK_SLASH 0x005c 92
VK_CLOSE_BRACKET 0x005d 93
VK_NUMPAD0 0x0060 96
VK_NUMPAD1 0x0061 97
VK_NUMPAD2 0x0062 98
VK_NUMPAD3 0x0063 99
VK_NUMPAD4 0x0064 100
VK_NUMPAD5 0x0065 101
VK_NUMPAD6 0x0066 102
VK_NUMPAD7 0x0067 103
VK_NUMPAD8 0x0068 104
VK_NUMPAD9 0x0069 105
VK_MULTIPLY 0x006a 106
VK_ADD 0x006b 107
VK_SEPARATER 0x006c 108
VK_SEPARATOR 0x006c 108
VK_SUBTRACT 0x006d 109
VK_DECIMAL 0x006e 110
VK_DIVIDE 0x006f 111
VK_F1 0x0070 112
VK_F2 0x0071 113
VK_F3 0x0072 114
VK_F4 0x0073 115
VK_F5 0x0074 116
VK_F6 0x0075 117
VK_F7 0x0076 118
VK_F8 0x0077 119
VK_F9 0x0078 120
VK_F10 0x0079 121
VK_F11 0x007a 122
VK_F12 0x007b 123
VK_DELETE (ASCII (American Standard Code for Information Interchange) del) 0x007f 127
VK_DEAD_GRAVE 0x0080 128
VK_DEAD_ACUTE 0x0081 129
VK_DEAD_CIRCUMFLEX 0x0082 130
VK_DEAD_TILDE 0x0083 131
VK_DEAD_MACRON 0x0084 132
VK_DEAD_BREVE 0x0085 133
VK_DEAD_ABOVEDOT 0x0086 134
VK_DEAD_DIAERESIS 0x0087 135
VK_DEAD_ABOVERING 0x0088 136
VK_DEAD_DOUBLEACUTE 0x0089 137
VK_DEAD_CARON 0x008a 138
VK_DEAD_CEDILLA 0x008b 139
VK_DEAD_OGONEK 0x008c 140
VK_DEAD_IOTA 0x008d 141
VK_DEAD_VOICED_SOUND 0x008e 142
VK_DEAD_SEMIVOICED_SOUND 0x008f 143
VK_NUM_LOCK 0x0090 144
VK_SCROLL_LOCK 0x0091 145
VK_AMPERSAND 0x0096 150
VK_ASTERISK 0x0097 151
VK_QUOTEDBL 0x0098 152
VK_LESS 0x0099 153
VK_PRINTSCREEN 0x009a 154
VK_INSERT 0x009b 155
VK_HELP 0x009c 156
VK_META 0x009d 157
VK_GREATER 0x00a0 160
VK_BRACELEFT 0x00a1 161
VK_BRACERIGHT 0x00a2 162
VK_BACK_QUOTE 0x00c0 192
VK_QUOTE 0x00de 222
VK_KP_UP 0x00e0 224
VK_KP_DOWN 0x00e1 225
VK_KP_LEFT 0x00e2 226
VK_KP_RIGHT 0x00e3 227
VK_ALPHANUMERIC 0x00f0 240
VK_KATAKANA 0x00f1 241
VK_HIRAGANA 0x00f2 242
VK_FULL_WIDTH 0x00f3 243
VK_HALF_WIDTH 0x00f4 244
VK_ROMAN_CHARACTERS 0x00f5 245
VK_ALL_CANDIDATES 0x0100 256
VK_PREVIOUS_CANDIDATE 0x0101 257
VK_CODE_INPUT 0x0102 258
VK_JAPANESE_KATAKANA 0x0103 259
VK_JAPANESE_HIRAGANA 0x0104 260
VK_JAPANESE_ROMAN 0x0105 261
VK_KANA_LOCK 0x0106 262
VK_INPUT_METHOD_ON_OFF 0x0107 263
VK_AT 0x0200 512
VK_COLON 0x0201 513
VK_CIRCUMFLEX 0x0202 514
VK_DOLLAR 0x0203 515
VK_EURO_SIGN 0x0204 516
VK_EXCLAMATION_MARK 0x0205 517
VK_INVERTED_EXCLAMATION_MARK 0x0206 518
VK_LEFT_PARENTHESIS 0x0207 519
VK_NUMBER_SIGN 0x0208 520
VK_PLUS 0x0209 521
VK_RIGHT_PARENTHESIS 0x020a 522
VK_UNDERSCORE 0x020b 523
VK_WINDOWS 0x020c 524
VK_CONTEXT_MENU 0x020d 525
VK_F13 0xf000 61440
VK_F14 0xf001 61441
VK_F15 0xf002 61442
VK_F16 0xf003 61443
VK_F17 0xf004 61444
VK_F18 0xf005 61445
VK_F19 0xf006 61446
VK_F20 0xf007 61447
VK_F21 0xf008 61448
VK_F22 0xf009 61449
VK_F23 0xf00a 61450
VK_F24 0xf00b 61451
VK_COMPOSE 0xff20 65312
VK_BEGIN 0xff58 65368
VK_ALT_GRAPH 0xff7e 65406
VK_STOP 0xffc8 65480
VK_AGAIN 0xffc9 65481
VK_PROPS 0xffca 65482
VK_UNDO 0xffcb 65483
VK_COPY 0xffcd 65485
VK_PASTE 0xffcf 65487
VK_FIND 0xffd0 65488
VK_CUT 0xffd1 65489
Alpha Ordering
name hex decimal
VK_0 0x0030 48
VK_1 0x0031 49
VK_2 0x0032 50
VK_3 0x0033 51
VK_4 0x0034 52
VK_5 0x0035 53
VK_6 0x0036 54
VK_7 0x0037 55
VK_8 0x0038 56
VK_9 0x0039 57
VK_A 0x0041 65
VK_ACCEPT 0x001e 30
VK_ADD 0x006b 107
VK_AGAIN 0xffc9 65481
VK_ALL_CANDIDATES 0x0100 256
VK_ALPHANUMERIC 0x00f0 240
VK_ALT 0x0012 18
VK_ALT_GRAPH 0xff7e 65406
VK_AMPERSAND 0x0096 150
VK_ASTERISK 0x0097 151
VK_AT 0x0200 512
VK_B 0x0042 66
VK_BACK_QUOTE 0x00c0 192
VK_BACK_SLASH 0x005c 92
VK_BACK_SPACE (\b) 0x0008 8
VK_BEGIN 0xff58 65368
VK_BRACELEFT 0x00a1 161
VK_BRACERIGHT 0x00a2 162
VK_C 0x0043 67
VK_CANCEL 0x0003 3
VK_CAPS_LOCK 0x0014 20
VK_CIRCUMFLEX 0x0202 514
VK_CLEAR 0x000c 12
VK_CLOSE_BRACKET 0x005d 93
VK_CODE_INPUT 0x0102 258
VK_COLON 0x0201 513
VK_COMMA 0x002c 44
VK_COMPOSE 0xff20 65312
VK_CONTEXT_MENU 0x020d 525
VK_CONTROL 0x0011 17
VK_CONVERT 0x001c 28
VK_COPY 0xffcd 65485
VK_CUT 0xffd1 65489
VK_D 0x0044 68
VK_DEAD_ABOVEDOT 0x0086 134
VK_DEAD_ABOVERING 0x0088 136
VK_DEAD_ACUTE 0x0081 129
VK_DEAD_BREVE 0x0085 133
VK_DEAD_CARON 0x008a 138
VK_DEAD_CEDILLA 0x008b 139
VK_DEAD_CIRCUMFLEX 0x0082 130
VK_DEAD_DIAERESIS 0x0087 135
VK_DEAD_DOUBLEACUTE 0x0089 137
VK_DEAD_GRAVE 0x0080 128
VK_DEAD_IOTA 0x008d 141
VK_DEAD_MACRON 0x0084 132
VK_DEAD_OGONEK 0x008c 140
VK_DEAD_SEMIVOICED_SOUND 0x008f 143
VK_DEAD_TILDE 0x0083 131
VK_DEAD_VOICED_SOUND 0x008e 142
VK_DECIMAL 0x006e 110
VK_DELETE (ASCII del) 0x007f 127
VK_DIVIDE 0x006f 111
VK_DOLLAR 0x0203 515
VK_DOWN 0x0028 40
VK_E 0x0045 69
VK_END 0x0023 35
VK_ENTER (\n) 0x000a 10
VK_EQUALS 0x003d 61
VK_ESCAPE 0x001b 27
VK_EURO_SIGN 0x0204 516
VK_EXCLAMATION_MARK 0x0205 517
VK_F 0x0046 70
VK_F1 0x0070 112
VK_F10 0x0079 121
VK_F11 0x007a 122
VK_F12 0x007b 123
VK_F13 0xf000 61440
VK_F14 0xf001 61441
VK_F15 0xf002 61442
VK_F16 0xf003 61443
VK_F17 0xf004 61444
VK_F18 0xf005 61445
VK_F19 0xf006 61446
VK_F2 0x0071 113
VK_F20 0xf007 61447
VK_F21 0xf008 61448
VK_F22 0xf009 61449
VK_F23 0xf00a 61450
VK_F24 0xf00b 61451
VK_F3 0x0072 114
VK_F4 0x0073 115
VK_F5 0x0074 116
VK_F6 0x0075 117
VK_F7 0x0076 118
VK_F8 0x0077 119
VK_F9 0x0078 120
VK_FINAL 0x0018 24
VK_FIND 0xffd0 65488
VK_FULL_WIDTH 0x00f3 243
VK_G 0x0047 71
VK_GREATER 0x00a0 160
VK_H 0x0048 72
VK_HALF_WIDTH 0x00f4 244
VK_HELP 0x009c 156
VK_HIRAGANA 0x00f2 242
VK_HOME 0x0024 36
VK_I 0x0049 73
VK_INPUT_METHOD_ON_OFF 0x0107 263
VK_INSERT 0x009b 155
VK_INVERTED_EXCLAMATION_MARK 0x0206 518
VK_J 0x004a 74
VK_JAPANESE_HIRAGANA 0x0104 260
VK_JAPANESE_KATAKANA 0x0103 259
VK_JAPANESE_ROMAN 0x0105 261
VK_K 0x004b 75
VK_KANA 0x0015 21
VK_KANA_LOCK 0x0106 262
VK_KANJI 0x0019 25
VK_KATAKANA 0x00f1 241
VK_KP_DOWN 0x00e1 225
VK_KP_LEFT 0x00e2 226
VK_KP_RIGHT 0x00e3 227
VK_KP_UP 0x00e0 224
VK_L 0x004c 76
VK_LEFT 0x0025 37
VK_LEFT_PARENTHESIS 0x0207 519
VK_LESS 0x0099 153
VK_M 0x004d 77
VK_META 0x009d 157
VK_MINUS 0x002d 45
VK_MODECHANGE 0x001f 31
VK_MULTIPLY 0x006a 106
VK_N 0x004e 78
VK_NONCONVERT 0x001d 29
VK_NUM_LOCK 0x0090 144
VK_NUMBER_SIGN 0x0208 520
VK_NUMPAD0 0x0060 96
VK_NUMPAD1 0x0061 97
VK_NUMPAD2 0x0062 98
VK_NUMPAD3 0x0063 99
VK_NUMPAD4 0x0064 100
VK_NUMPAD5 0x0065 101
VK_NUMPAD6 0x0066 102
VK_NUMPAD7 0x0067 103
VK_NUMPAD8 0x0068 104
VK_NUMPAD9 0x0069 105
VK_O 0x004f 79
VK_OPEN_BRACKET 0x005b 91
VK_P 0x0050 80
VK_PAGE_DOWN 0x0022 34
VK_PAGE_UP 0x0021 33
VK_PASTE 0xffcf 65487
VK_PAUSE 0x0013 19
VK_PERIOD 0x002e 46
VK_PLUS 0x0209 521
VK_PREVIOUS_CANDIDATE 0x0101 257
VK_PRINTSCREEN 0x009a 154
VK_PROPS 0xffca 65482
VK_Q 0x0051 81
VK_QUOTE 0x00de 222
VK_QUOTEDBL 0x0098 152
VK_R 0x0052 82
VK_RIGHT 0x0027 39
VK_RIGHT_PARENTHESIS 0x020a 522
VK_ROMAN_CHARACTERS 0x00f5 245
VK_S 0x0053 83
VK_SCROLL_LOCK 0x0091 145
VK_SEMICOLON 0x003b 59
VK_SEPARATER 0x006c 108
VK_SEPARATOR 0x006c 108
VK_SHIFT 0x0010 16
VK_SLASH 0x002f 47
VK_SPACE 0x0020 32
VK_STOP 0xffc8 65480
VK_SUBTRACT 0x006d 109
VK_T 0x0054 84
VK_TAB (\t) 0x0009 9
VK_U 0x0055 85
VK_UNDEFINED 0x0000 0
VK_UNDERSCORE 0x020b 523
VK_UNDO 0xffcb 65483
VK_UP 0x0026 38
VK_V 0x0056 86
VK_W 0x0057 87
VK_WINDOWS 0x020c 524
VK_X 0x0058 88
VK_Y 0x0059 89
VK_Z 0x005a 90

Event vs. AWTEvent

In JDK 1.0.2 there was basically only one kind of Event, called the java.awt.Event. In  Java version 1.6 or later there is a base Event called a java.awt.event.AWTEvent. All the other types of Event such as java.awt.event.actionEvent and java.awt.event.WindowEvent are derived from it. It is a bit confusing since the Event package for Java version 1.6 or later is called java.awt.event instead of java.awt.AWTEvent as you might expect.

Synthetic Events

There are a number of ways to fake an event.
  1. Check out Oracle’s java.awt.Robot class for generating simulated keystrokes and mouse moves.
  2. The simplest is just to call a Listener method directly with a dummy Event object, filled in with just enough data to keep the method happy.
  3. Create an Event and introduce it to the Component that will handle it at the processEvent method. with:
  4. Create an Event and
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent( Event e );
  5. Generating MouseMoved Events has no effect on the screen mouse cursor. To make the underlying native GUI see your generated Events, use the Robot class to generate move clicks, moves etc.
    // synthetic native gui events
    import java.awt.event.InputEvent;
    import java.awt.event.KeyEvent;
    import java.awt.Robot;
    ...
    Robot r = new Robot();
    r.mouseMove( 100, 100 );
    r.keyPress( KeyEvent.VK_A );
    r.mousePress( InputEvent.BUTTON1_MASK );

Changes from JDK 1.0

In addition to the complete revamping of how it works inside, some of the interfacing details have changed too. The names of the various Events no longer live in the Event class. They live in the various subclasses of AWTEvent e.g. WindowEvent.WINDOW_CLOSED. Some Events have been renamed. WINDOW_DESTROY is now WINDOW_CLOSED. You can no longer access the source and id fields of an Event directly. You must call getSource and getID. handleEvent is now called processEvent. See my essay on JDK 1.0 events, primarily now of historical interest.

Changes with Java version 1.3

Starting with Java version 1.3 it is possible to insert custom Events into the system Event queue with awt.EventQueue.invokeLater( Runnable r ) (or invokeAndWait). It also appears to be possible to take direct control of the Event queue by sub-classing it using getToolkit().getSystemEventQueue().push( subclass of awt.EventQueue). You could then add some monitoring debug code for example.

The catch is MouseEvents you create this way don’t move the mouse cursor. To insert native events that will, see the Robot class. It can also be used to generate synthetic keystroke events. The Robot class helps you create self running demos.

Repaint

You may have seen mention of PaintEvent.PAINT and PaintEvent.UPDATE events. These are used to control how components are repainted. The repaint mechanism partly uses the SystemEventQueue and partly the queue inside the native GUI. See repaint in the Java & Internet Glossary for details on how it works.

Learning More

Oracle’s Javadoc on EventQueue class : available:

Credits

This article would not have been possible without the patient assistance of Jan Newmarch who researched the material.
book cover recommend book⇒Tricks of The Java Programing Gurusto book home
by Glenn L. Vanderburg 978-1-57521-102-2 paperback
publisher Sams
published 1996-07
Chapter by Jan Newmarch
Australian flag abe books anz abe books.co.uk UK flag
Chinese flag amazon.cn amazon.co.uk UK flag
German flag abe books.de abe books.ca Canadian flag
German flag amazon.de amazon.ca Canadian flag
Spanish flag amazon.es Chapters Indigo Canadian flag
Spanish flag iberlibro.com abe books.com American flag
French flag abe books.fr amazon.com American flag
French flag amazon.fr Barnes & Noble American flag
Italian flag abe books.it Google play American flag
Italian flag amazon.it O’Reilly Safari American flag
India flag junglee.com Powells American flag
UN flag Kobo other stores UN flag
Greyed out stores probably do not have the item in stock. Try looking for it with a bookfinder.
Richard Baldwin and Peter Mehlitz helped explain the Java version 1.1 or later event processing. Steve Odendahl pointed out the mismatched signature problem in Adapters. Tuyen Tran pointed out the problems with Swing and threading.

Summary

The key point to understand is that a component has two kinds of acceptor routines for Events. The generic processEvent routine primarily accepts events coming indirectly from the native GUI which it then fobs off on the more specific processXXXXEvent methods. The listener methods, e.g. actionPerformed, accept Events from other components. The listener methods are primarily for application programmers and those who customise existing components; the processXXXXEvent methods are primarily for the writers of radically new components.

This page is posted
on the web at:

http://mindprod.com/jgloss/event11.html

Optional Replicator mirror
of mindprod.com
on local hard disk J:

J:\mindprod\jgloss\event11.html
logo
Please the feedback from other visitors, or your own feedback about the site.
Contact Roedy. Please feel free to link to this page without explicit permission.
Blog
IP:[65.110.21.43]
Your face IP:[50.17.27.205]
You are visitor number