Event Summary

Tables 16-1 and 16-2 summarize commonly used Swing events, which Swing components fire them, and the methods of the listener interfaces that receive them. The events and listeners are divided between the java.awt.event and javax.swing.event packages.

Table 16-1. Swing component and container events

Event

Fired by

Listener interface

Handler methods

java.awt.event.ComponentEvent

All components

ComponentListener

componentResized( ) componentMoved( ) componentShown( ) componentHidden( )

java.awt.event.FocusEvent

All components

FocusListener

focusGained( ) focusLost( )

java.awt.event.KeyEvent

All components

KeyListener

keyTyped( ) keyPressed( ) keyReleased( )

java.awt.event.MouseEvent

All components

MouseListener

mouseClicked( ) mousePressed( ) mouseReleased( ) mouseEntered( ) mouseExited( )

   

MouseMotionListener

mouseDragged( ) mouseMoved( )

java.awt.event.ContainerEvent

All containers

ContainerListener

componentAdded( ) componentRemoved( )


Table 16-2. Component-specific swing events

Event

Fired by

Listener interface

Handler method

java.awt.event.ActionEvent

JButton JCheckBoxMenuItem JComboBox JFileChooser JList JRadioButtonMenuItem JTextField JToggleButton

ActionListener

actionPerformed( )

java.awt.event.AdjustmentEvent

JScrollBar

Adjustment-Listener

adjustmentValue-Changed( )

javax.swing.event.CaretEvent

JTextComponent

CaretListener

caretUpdate( )

javax.swing.event.HyperlinkEvent

JEditorPane JTextPane

Hyperlink-Listener

hyperlinkUpdate( )

java.awt.event.InternalFrameEvent

JInternalFrame

InternalFrame-Listener

internalFrame-Activated( ) internalFrame-Closed( ) internalFrame-Closing( ) internalFrame-Deactivated( ) internalFrame-Deiconified( ) internalFrame-Iconified( ) internalFrame-Opened( )

java.awt.event.ItemEvent

JCheckBoxMenuItem JComboBox JRadioButtonMenuItem JToggleButton

ItemListener

itemStateChanged( )

javax.swing.event.ListDataEvent

ListModel

ListDataListener

contentsChanged( ) intervalAdded( ) intervalRemoved( )

javax.swing.event.ListSelectionEvent

JList ListSelectionModel

ListSelection-Listener

valueChanged( )

javax.swing.event.MenuEvent

JMenu

MenuListener

menuCanceled( ) menuDeselected( ) menuSelected( )

javax.swing.event.PopupMenuEvent

JPopupMenu

PopupMenu-Listener

popupMenuCanceled( ) popupMenuWill-BecomeInvisible( ) popupMenuWill-BecomeVisible( )

javax.swing.event.MenuKeyEvent

JMenuItem

MenuKeyListener

menuKeyPressed( ) menuKeyReleased( ) menuKeyTyped( )

javax.swing.event.MenuDragMouseEvent

JMenuItem

MenuDragMouse-Listener

menuDragMouse-Dragged( ) menuDragMouse-Entered( ) menuDragMouse-Exited( ) menuDragMouse-Released( )

javax.swing.event.TableColumnModel-Event

TableColumnModela

TableColumn-ModelListener

columnAdded( ) columnMargin-Changed( ) columnMoved( ) columnRemoved( ) columnSelection-Changed( )

javax.swing.event.TableModelEvent

TableModel

TableModel-Listener

tableChanged( )

javax.swing.event.TreeExpansionEvent

Jtree

treeExpansion-Listener

treeCollapsed( ) TReeExpanded( )

javax.swing.event.TreeModelEvent

treeModel

treeModel-Listener

treeNodesChanged( ) TReeNodesInserted( ) TReeNodesRemoved( ) treeStructure-Changed( )

javax.swing.event.TreeSelectionEvent

Jtree treeSelectionModel

treeSelection-Listener

valueChanged( )

javax.swing.event.UndoableEditEvent

javax.swing.text.Document

UndoableEdit-Listener

undoableEdit-Happened( )

java.awt.event.WindowEvent

JDialog JFrame JWindow

WindowListener

windowOpened( ) windowClosing( ) windowClosed( ) windowIconified( ) windowDeiconified( ) windowActivated( ) windowDeactivated( )

The TableColumnModel class breaks with convention in the names of the methods that add listeners. They are addColumnModelListener( ) and removeColumnModelListener( ).


In Swing, a component's model and view are distinct. Strictly speaking, components don't fire events; models do. When you press a JButton, for example, it's actually the button's data model that fires an ActionEvent, not the button itself. But JButton has a convenience method for registering ActionListeners; this method passes its argument through to register the listener with the button model. In many cases (as with JButtons), you don't have to deal with the data model separately from the view, so we can speak loosely of the component itself firing the events. InputEvents are, of course, generated by the native input system and fired for the appropriate component, although the listener responds as though they're generated by the component.

Adapter Classes

It's not ideal to have your app components implement a bunch of listener interfaces and receive events directly. Sometimes it's not even possible. Being an event receiver forces you to modify or subclass your objects to implement the appropriate event listener interfaces and add the code necessary to handle the events. And since we are talking about Swing events here, a more subtle issue is that you would be, of necessity, building GUI logic into parts of your app that shouldn't have to know anything about the GUI. Let's look at an example. In Screenshot-4, we have drawn the plans for our Vegomatic food processor. Here we have made our Vegomatic object implement the ActionListener interface so that it can receive events directly from the three JButton components: Chop, Puree, and Frappe. The problem is that our Vegomatic object now has to know more than how to mangle food. It also has to be aware that it is driven by three controlsspecifically, buttons that send action commandsand be aware of which methods it should invoke for those commands. Our boxes labeling the GUI and app code overlap in an unwholesome way. If the marketing people should later want to add or remove buttons or perhaps just change the names, we have to be careful. We may have to modify the logic in our Vegomatic object. All is not well. An alternative is to place an adapter class between our event source and receiver. An adapter is a simple object whose sole purpose is to map an incoming event to an outgoing method. Screenshot-5 shows a better design that uses three adapter classes, one for each button. The implementation of the first adapter might look like:

 class VegomaticAdapter1 implements ActionListener {
 Vegomatic vegomatic;
 VegomaticAdapter1 ( Vegomatic vegomatic ) {
 this.vegomatic = vegomatic;
 }
 public void actionPerformed( ActionEvent e ) {
 vegomatic.chopFood( );
 }
 }


Screenshot-4. Implementing the ActionListener interface directly
Java ScreenShot

Screenshot-5. Implementing the ActionListener interface using adapter classes
Java ScreenShot

So, somewhere in the code where we build our GUI, we could register our listener like this:

 Vegomatic theVegomatic = ...;
 Button chopButton = ...;
 // make the hookup
 chopButton.addActionListener( new VegomaticAdapter1(theVegomatic) );


Instead of registering itself (this) as the Button's listener, the adapter registers the Vegomatic object (theVegomatic). In this way, the adapter acts as an intermediary, hooking up an event source (the button) with an event receiver (the virtual chopper). We have completely separated the messiness of our GUI from the app code. However, we have added three new classes to our app, none of which does very much. Is that good? It depends on your vantage point. Under different circumstances, our buttons may have been able to share a common adapter class that was simply instantiated with different parameters. Various trade-offs can be made between size, efficiency, and elegance of code. Adapter classes will often be generated automatically by development tools. The way we have named our adapter classes VegomaticAdapter1, VegomaticAdapter2, and VegomaticAdapter3 hints at this. More often, when hand-coding, you'll use an anonymous inner class, as we'll see in the next section. At the other extreme, we can forsake Java's strong typing and use the Reflection API to create a completely dynamic hookup between an event source and its listener.

Dummy Adapters

Many listener interfaces contain more than one event-handler method. Unfortunately, this means that to register yourself as interested in any one of those events, you must implement the whole listener interface. To accomplish this, you might find yourself typing dummy "stubbed-out" methods to complete the interface. There is nothing wrong with this, but it is a bit tedious. To save you some trouble, AWT and Swing provide some helper classes that implement these dummy methods for you. For each of the most common listener interfaces containing more than one method, there is an adapter class containing the stubbed methods. You can use the adapter class as a base class for your own adapters. When you need a class to patch together your event source and listener, you can subclass the adapter and override only the methods you want. For example, the MouseAdapter class implements the MouseListener interface and provides the following minimalist implementation:

 public void mouseClicked(MouseEvent e) {};
 public void mousePressed(MouseEvent e) {};
 public void mouseReleased(MouseEvent e) {};
 public void mouseEntered(MouseEvent e) {};
 public void mouseExited(MouseEvent e) {};


This isn't a tremendous time saver; it's simply a bit of sugar. The primary advantage comes into play when we use the MouseAdapter as the base for our own adapter in an anonymous inner class. For example, suppose we want to catch a mousePressed( ) event in some component and blow up a building. We can use the following to make the hookup:

 someComponent.addMouseListener( new MouseAdapter( ) {
 public void MousePressed(MouseEvent e) {
 building.blowUp( );
 }
 } );


We've taken artistic liberties with the formatting, but it's pretty readable. Moreover, we've avoided creating stub methods for the four unused event-handler methods. Writing adapters is common enough that it's nice to avoid typing those extra few lines and perhaps stave off the onset of carpal tunnel syndrome for a few more hours. Remember that any time you use an inner class, the compiler is generating a class for you, so the messiness you've saved in your source still exists in the output classes.

Java ScreenShot
Comments