事件和吸收者范例(java)
所有AWT组件都被改酿成包括addXXXListener()和removeXXXListener()要领,因此特定的吸收器范例可从每个组件中增加和删除。
我们会留意到“XXX”在每个场所中同样暗示自变量的要领,譬喻,addFooListener(FooListener fl)。
下面这张表格总结了通过提供addXXXListener()和removeXXXListener()要领,从而支持那些特定事件的相关事件、吸收器、要领以及组件。
事件,吸收器接口及添加和删除要领 支持这个事件的组件
Event, listener interface and add- and remove-methods |
Components supporting this event |
---|---|
ActionEvent |
Button, List, TextField, MenuItem, and its derivatives including CheckboxMenuItem, Menu, and PopupMenu |
AdjustmentEvent |
Scrollbar |
ComponentEvent |
Component and its derivatives, including Button, Canvas, Checkbox, Choice, Container, Panel, Applet, ScrollPane, Window, Dialog, FileDialog, Frame, Label, List, Scrollbar, TextArea, and TextField |
ContainerEvent |
Container and its derivatives, including Panel, Applet, ScrollPane, Window, Dialog, FileDialog, and Frame |
FocusEvent |
Component and its derivatives, including Button, Canvas, Checkbox, Choice, Container, Panel, Applet, ScrollPane, Window, Dialog, FileDialog, Frame Label, List, Scrollbar, TextArea, and TextField |
KeyEvent |
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) |
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) |
Component and its derivatives, including Button, Canvas, Checkbox, Choice, Container, Panel, Applet, ScrollPane, Window, Dialog, FileDialog, Frame, Label, List, Scrollbar, TextArea, and TextField |
WindowEvent |
Window and its derivatives, including Dialog, FileDialog, and Frame |
ItemEvent |
#p#分页标题#e#
Checkbox, CheckboxMenuItem, Choice, List, and anything that implements the ItemSelectable interface |
TextEvent |
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 |
#p#分页标题#e#
一旦知道了一个特定的组件支持哪些事件,就不必再去寻找任何对象来响应谁人事件。只需简朴地:
(1) 取得事件类的名字,并删掉个中的“Event”字样。在剩下的部门插手“Listener”字样。这就是在我们的内部类里需要实现的吸收器接口。
(2) 实现上面的接口,针对想要捕捉的事件编写要领代码。譬喻,假设我们想捕捉鼠标的移动,所以需要为MouseMotiionListener接口的mouseMoved()要领编写代(虽然还必需实现其他一些要领,但这里有捷径可循,顿时就会讲到这个问题)。
(3) 为步调2中的吸收器类建设一个工具。随本身的组件和要领完成对它的注册,要领是在吸收器的名字里插手一个前缀“add”。好比addMouseMotionListener()。
下表是对吸收器接口的一个总结:
吸收器接口 接口中的要领
Listener interface |
Methods in interface |
---|---|
ActionListener |
actionPerformed(ActionEvent) |
AdjustmentListener |
adjustmentValueChanged( |
ComponentListener |
#p#分页标题#e#
componentHidden(ComponentEvent) |
ContainerListener |
componentAdded(ContainerEvent) |
FocusListener |
focusGained(FocusEvent) |
KeyListener |
keyPressed(KeyEvent) |
MouseListener |
mouseClicked(MouseEvent) |
MouseMotionListener |
mouseDragged(MouseEvent) |
WindowListener |
windowOpened(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()。巨细写的一个简朴失误就会造成一个崭新的要领。可是,这并非我们封锁窗口时挪用的要领,所以虽然没有任何结果。