所有AWT組件都被改變成包含addXXXListener()和removeXXXListener()方法,因此特定的接收器類型可從每個組件中增加和刪除。
我們會注意到“XXX”在每個場合中同樣表示自變量的方法,例如,addFooListener(FooListener fl)。
下面這張表格總結了通過提供addXXXListener()和removeXXXListener()方法,從而支持那些特定事件的相關事件、接收器、方法以及組件。
事件,接收器接口及添加和刪除方法 支持這個事件的組件
Event, listener interface and add- and remove-methods
Components supporting this event
ActionEvent
ActionListener
addActionListener()
removeActionListener()
Button, List, TextField, MenuItem, and its derivatives including CheckboxMenuItem, Menu, and PopupMenu
AdjustmentEvent
AdjustmentListener
addAdjustmentListener()
removeAdjustmentListener()
Scrollbar
Anything you create that implements the Adjustable interface
ComponentEvent
ComponentListener
addComponentListener()
removeComponentListener()
Component and its derivatives, including Button, Canvas, Checkbox, Choice, Container, Panel, Applet, ScrollPane, Window, Dialog, FileDialog, Frame, Label, List, Scrollbar, TextArea, and TextField
ContainerEvent
ContainerListener
addContainerListener()
removeContainerListener()
Container and its derivatives, including Panel, Applet, ScrollPane, Window, Dialog, FileDialog, and Frame
FocusEvent
FocusListener
addFocusListener()
removeFocusListener()
Component and its derivatives, including Button, Canvas, Checkbox, Choice, Container, Panel, Applet, ScrollPane, Window, Dialog, FileDialog, Frame Label, List, Scrollbar, TextArea, and TextField
KeyEvent
KeyListener
addKeyListener()
removeKeyListener()
Component and its derivatives, including Button, Canvas, Checkbox, Choice, Container, Panel, Applet, ScrollPane, Window, Dialog, FileDialog, Frame, Label, List, Scrollbar, TextArea, and TextField
MouseEvent (for both clicks and motion)
MouseListener
addMouseListener()
removeMouseListener()
Component and its derivatives, including Button, Canvas, Checkbox, Choice, Container, Panel, Applet, ScrollPane, Window, Dialog, FileDialog, Frame, Label, List, Scrollbar, TextArea, and TextField
MouseEvent[55] (for both clicks and motion)
MouseMotionListener
addMouseMotionListener()
removeMouseMotionListener()
Component and its derivatives, including Button, Canvas, Checkbox, Choice, Container, Panel, Applet, ScrollPane, Window, Dialog, FileDialog, Frame, Label, List, Scrollbar, TextArea, and TextField
WindowEvent
WindowListener
addWindowListener()
removeWindowListener()
Window and its derivatives, including Dialog, FileDialog, and Frame
ItemEvent
ItemListener
addItemListener()
removeItemListener()
Checkbox, CheckboxMenuItem, Choice, List, and anything that implements the ItemSelectable interface
TextEvent
TextListener
addTextListener()
removeTextListener()
Anything derived from TextComponent, including TextArea and TextField
⑤:即使表面上如此,但實際上並沒有MouseMotiionEvent(鼠標運動事件)。單擊和運動都合成到MouseEvent裡,所以MouseEvent在表格中的這種另類行為並非一個錯誤。
可以看到,每種類型的組件只為特定類型的事件提供了支持。這有助於我們發現由每種組件支持的事件,如下表所示:
組件類型 支持的事件
Component type
Events supported by this component
Adjustable
AdjustmentEvent
Applet
ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
Button
ActionEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
Canvas
FocusEvent, KeyEvent, MouseEvent, ComponentEvent
Checkbox
ItemEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
CheckboxMenuItem
ActionEvent, ItemEvent
Choice
ItemEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
Component
FocusEvent, KeyEvent, MouseEvent, ComponentEvent
Container
ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
Dialog
ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
FileDialog
ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
Frame
ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
Label
FocusEvent, KeyEvent, MouseEvent, ComponentEvent
List
ActionEvent, FocusEvent, KeyEvent, MouseEvent, ItemEvent, ComponentEvent
Menu
ActionEvent
MenuItem
ActionEvent
Panel
ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
PopupMenu
ActionEvent
Scrollbar
AdjustmentEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
ScrollPane
ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
TextArea
TextEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
TextComponent
TextEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
TextField
ActionEvent, TextEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
Window
ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent
一旦知道了一個特定的組件支持哪些事件,就不必再去尋找任何東西來響應那個事件。只需簡單地:
(1) 取得事件類的名字,並刪掉其中的“Event”字樣。在剩下的部分加入“Listener”字樣。這就是在我們的內部類裡需要實現的接收器接口。
(2) 實現上面的接口,針對想要捕獲的事件編寫方法代碼。例如,假設我們想捕獲鼠標的移動,所以需要為MouseMotiionListener接口的mouseMoved()方法編寫代(當然還必須實現其他一些方法,但這裡有捷徑可循,馬上就會講到這個問題)。
(3) 為步驟2中的接收器類創建一個對象。隨自己的組件和方法完成對它的注冊,方法是在接收器的名字裡加入一個前綴“add”。比如addMouseMotionListener()。
下表是對接收器接口的一個總結:
接收器接口 接口中的方法
Listener interface
w/ adapter
Methods in interface
ActionListener
actionPerformed(ActionEvent)
AdjustmentListener
adjustmentValueChanged(
AdjustmentEvent)
ComponentListener
ComponentAdapter
componentHidden(ComponentEvent)
componentShown(ComponentEvent)
componentMoved(ComponentEvent)
componentResized(ComponentEvent)
ContainerListener
ContainerAdapter
componentAdded(ContainerEvent)
componentRemoved(ContainerEvent)
FocusListener
FocusAdapter
focusGained(FocusEvent)
focusLost(FocusEvent)
KeyListener
KeyAdapter
keyPressed(KeyEvent)
keyReleased(KeyEvent)
keyTyped(KeyEvent)
MouseListener
MouseAdapter
mouseClicked(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
MouseMotionListener
MouseMotionAdapter
mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
WindowListener
WindowAdapter
windowOpened(WindowEvent)
windowClosing(WindowEvent)
windowClosed(WindowEvent)
windowActivated(WindowEvent)
windowDeactivated(WindowEvent)
windowIconified(WindowEvent)
windowDeiconified(WindowEvent)
ItemListener
itemStateChanged(ItemEvent)
TextListener
textValueChanged(TextEvent)
1. 用接收器適配器簡化操作
在上面的表格中,我們可以注意到一些接收器接口只有唯一的一個方法。它們的執行是無輕重的,因為我們僅當需要書寫特殊方法時才會執行它們。然而,接收器接口擁有多個方法,使用起來卻不太友好。例如,我們必須一直運行某些事物,當我們創建一個應用程序時對幀提供一個WindowListener,以便當我們得到windowClosing()事件時可以調用System.exit(0)以退出應用程序。但因為WindowListener是一個接口,我們必須執行其它所有的方法即使它們不運行任何事件。這真令人討厭。
為了解決這個問題,每個擁有超過一個方法的接收器接口都可擁有適配器,它們的名我們可以在上面的表格中看到。每個適配器為每個接口方法提供默認的方法。(WindowAdapter的默認方法不是windowClosing(),而是System.exit(0)方法。)此外我們所要做的就是從適配器處繼承並過載唯一的需要變更的方法。例如,典型的WindowListener我們會像下面這樣的使用。
class MyWindowListener extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } }
適配器的全部宗旨就是使接收器的創建變得更加簡便。
但所謂的“適配器”也有一個缺點,而且較難發覺。假定我們象上面那樣寫一個WindowAdapter:
class MyWindowListener extends WindowAdapter { public void WindowClosing(WindowEvent e) { System.exit(0); } }
表面上一切正常,但實際沒有任何效果。每個事件的編譯和運行都很正常——只是關閉窗口不會退出程序。您注意到問題在哪裡嗎?在方法的名字裡:是WindowClosing(),而不是windowClosing()。大小寫的一個簡單失誤就會造成一個嶄新的方法。但是,這並非我們關閉窗口時調用的方法,所以當然沒有任何效果。