您的位置:首页 > 编程语言 > Java开发

事件处理 - core java

2010-06-28 11:16 155 查看
8. 事件处理 - core java

事件处理包括: 事件源类.事件类.监听器接口.监听器适配器类 它们之间的关系.
其中事件源是用户界面组件.窗口和菜单. 操作系统会把用户的动作通知给感兴趣的事件源. 事件源用一个
事件对象描述所发生事件的特性. 并且. 事件源可以注册一组监听器. 当事件发生时会把事件对象传递给
这些监听器对象. 由监听器对象具体处理发生的事件.

各种事件类的继承层次:

AWTEvent
|
|-ActionEvent
|-AdjustmentEvent
|-ItemEvent
|-TextEvent
|-ComponentEvent
|-ContainerEvent
|-FocusEvent
|-PaintEvent
|-WindowEvent
|-InputEvent
|-KeyEvent
|-MouseEvent
|-MouseWheelEvent

每个事件类都有对应的监听器类. 如ItemEvent类对应的监听器接口ItemListener.监听器接口有:
ActionListener
AdjustmentListener
ComponenListener
ContainerListener
FocusListener
ItemListener
KeyListener
MouseListener
MouseMotionListener
MouseWheelListener
TextListener
WindowListener
WindowFocusListener
WindowStateListener

有的监听器接口中包括多个方法. 为了实现该接口时少写点代码. 提供了一些缺省适配类.
这些缺省适配类为接口中的每个方法提供了默认操作:
ComponentAdapter
ContainerAdapter
FocusAdapter
KeyAdapter
MouseAdapter
MouseMotionAdapter
WindowAdapter

8.3 AWT的语义事件和低层次事件

语义事件是明确表达用户动作的事件.如按下按钮.
低层事件是一些原始的事件.如按下按钮过程中可能会有鼠标左键按下.弹起等.

在java.awt.event包中有:

4个语义事件类
ActionEvent 对应按钮按下. 菜单选择. 列表项选择 或者文本域输入回车.
AdjustmentEvent 对应用户调整了滚动条.
ItemEvent 对应用户从一组选择框或列表项中选择
TextEvent 对应文本域或文本框中的内容发生改变.

6个低层事件类
ComponentEvent 组件被缩放/移动/显示/隐藏 这个类是所有低层次事件类的基类.
KeyEvent 一个键被按下/释放
MouseEvent 鼠标键被按下/释放 鼠标移动/拖动
MouseWheelEvent 鼠标轮被滚动
FocusEvent 组件得到焦点/失去焦点
WindowEvent 窗口被激活/减活/图标化/还原/关闭
ContainerEvent 添加/删除一个组件

8.4 低层事件类型

8.4.1 键盘事件
例如用户同时按下SHIFT和A. 则生成5个事件:
1.按SHIFT事件 2.按A事件 3."输入A"事件 4.释放A事件 5.释放SHIFT事件
监听这些键盘事件需要KeyListener接口. 该接口的方法如下:
void keyPressed(KeyEvent e) //按下
void keyReleased(KeyEvent e) //释放
void keyTyped(KeyEvent e) //键入字符
可以用参数e的 getKeyChar() 或 getKeyCode()来得到键的字符或相关整数(虚拟键代码).

8.4.2 鼠标事件
如果是处理象点击按钮或选择菜单等.则不需要鼠标事件这样的低层事件.
而对于画图等则需要处理这类事件.

鼠标可以产生的事件包括: 按下/释放 单击 进入/离开 移动 拖动 鼠标滚轮旋转 .
有两种事件监听器接口来监听处理MouseEvent.
其中:
接口MouseListener处理: 按下/释放 单击 进入/离开. 它的适配器类为MouseAdapter.
void mouseClicked(MouseEvent e) 单击键时
void mouseEntered(MouseEvent e) 进入组件时
void mouseExited(MouseEvent e) 离开组件时
void mousePressed(MouseEvent e) 按下键时
void mouseReleased(MouseEvent e) 释放键时
接口MouseMotionListener处理: 移动 拖动. 它的适配器类为MouseMotionAdapter.
void mouseDragged(MouseEvent e) 在组件上按下并拖动时
void mouseMoved(MouseEvent e) 移动到组件上但无按键按下时
使用两个监听器接口是为了效率. 因为大多时候我们并不想监听鼠标移动事件.
鼠标事件用MouseEvent类表示(除了鼠标滚轮事件).

类MouseEvent的方法有:
int getButton() 返回事件发生在哪个键上. 返回NOBUTTON BUTTON1 BUTTON2 BUTTON3之一.
int getClickCount() 返回与此事件关联的鼠标单击次数。
Point getPoint() 返回事件相对于源组件的 x、y 位置。
int getX() 返回事件相对于源组件的水平 x 坐标。
int getY() 返回事件相对于源组件的垂直 y 坐标。
String paramString() 返回标识此事件的参数字符串。 调试用.
void translatePoint(int x, int y) 将事件的坐标平移到新位置

另外. MouseEvent继承自 InputEvent类. 所以它继承的方法还有下边的:
public boolean isShiftDown()
public boolean isControlDown()
public boolean isMetaDown()
public boolean isAltDown()
public boolean isAltGraphDown()
public long getWhen()
public int getModifiers()
public int getModifiersEx()
使用这些方法可以知道事件发生时每个鼠标键是否按下.可以知道Shift/Ctrl/Alt等键是否按下.

最后我们还可以更改鼠标光标. 要更改鼠标光标先要加载它. 使用java.awt.Toolkit类的方法:
public Cursor createCustomCursor(Image image, Point hotSpot, String name)
其中参数: image是光标显示时的图像.
hotSpot是光标的坐标(例如可以指定为图像的顶点或图像的中心).
name是光标的说明.
加载光标后用java.awt.Component类的方法:
public void setCursor(Cursor cursor)
来设置光标.

8.4.3 焦点事件

例如文本框得到焦点时就会出现闪烁光标. 而按钮则在按钮标签周围显示矩形等.
同一个窗口中只能有一个组件具有焦点. 组件要得到焦点. 可能是用户点击了它. 也可能是使用Tab键切换的.
在组件得到或失去焦点时会产生FocusEvent事件. 要处理这些事件用监听器:
FocusListener接口(缺省适配器类是FocusAdapter)
它的方法有:
void focusGained(FocusEvent e) 获得键盘焦点
void focusLost(FocusEvent e) 失去键盘焦点

Component关于焦点的方法有:
void requestFocus() 请求把焦点转移到该组件上
void setFocusable(boolean ) 设置是否允许组件获得焦点.
boolean isFocusOwnwer() 检查组件是否已经获得焦点.

8.7 事件队列(core java 第6版)

当操作系统响应用户动作(如鼠标点击)时会生成操作系统事件. AWT把它转换为一个AWTEvent对象. 并添加到
事件队列中. 最后把AWTEvent从事件队列提取出来分派到合适的监听器上.调用监听器上对应的方法.

事件的处理可能需要较长的时间.所以产生的事件不可能立刻就被处理.所以要借助事件队列来缓冲一下.
我们也可以直接操作事件队列. 例如向事件队列中添加/删除事件对象. 这使用下边的函数如:
EventQueue queue = Toolkit.getDefaultToolkit().getSystemEventqQueue(); //取事件队列
queue.postEvent(new ActionEvent(...)); //构造了一个事件并将其添加到事件队列
提取出下一个事件和查看下一个事件使用EventQueue类的方法:
AWTEvent peekEvent(); //查看下一个事件对象 (但不从队列删除)
AWTEvent getNextEvent(); //取出下一个事件对象(并从队列删除)

定制自己的事件类型

本小节我们将定制自己的时间事件并处理它. 定制事件有三个要素:
事件类.
事件监听器接口.
事件源.

首先定义一个自定义事件类TimerEvent. 因为AWT事件队列中的事件必须是AWTEvent类型的. 所以我们这个
TimerEvent要从AWTEvent派生:
class TimerEvent extends AWTEvent {
public TimerEvent(Timer t) { super(t,TIMER_EVENT); } //调用基类的构造方法
//AWTEvent(Object source, int id)用指定的事件源和事件类型构造一个 AWTEvent 对象
public static final int TIMER_EVENT = AWTEvent.RESERVED_ID_MAX+5555;
}

其中构造方法参数中的Timer是我们自己的事件源类. 下边我们定义这个类. 因为AWT事件机制要求事件源要
扩展自Component类. 所以我们的事件源Timer类如下:

class Timer extends JComponent implements Runnable {
private int interval; //定时器事件的间隔时间
private EventListenerList listeners; //用来管理注册的监听器
///////////////////////////////////////////////////////////
// EventListenerList 类
// 用来管理注册的事件监听器对象. 它的方法包括(下边会用到这些方法):
// void add(Class<T> t, T l) //将监听器作为指定的类型添加
// void remove(Class<T> t, T l) //将监听器作为指定的类型移除
// T[] getListeners(Class<T> t) //返回给定类型的所有侦听器组成的数组
//////////////////////////////////////////////////////////////////////////

public Timer(int i) { //事件源的构造方法.
//它启动了一个线程. 该线程每隔interval时间会向事件队列加入一个
//TimerEvent对象.
interval = i;
Thread t = new Thread(this);
t.start();
}
public void run() {
while (true) {
try { Thread.sleep(interval); }
catch(InterruptedException e) {]
EventQueue queue = Toolkit.getDefaultToolkit().getSystemEventQueue();
TimerEvent event = new TimerEvent(this); //构造自定义事件并将它放入事件队列
queue.postEvent(event);
}
}
//此时我们已经让TimerEvent事件源源不断的插入AWT事件队列. 不过事情并没有结束. 因为我们
//还要对这些事件进行处理呀. 处理事件是监听器类做的事. 但我们的事件源类要有添加/删除监听器
//的方法. 管理这些监听器对象需要使用 EventListenerList类 . 如下:
public void addTimerListener(TimerListener listener) {
listenerList.add(TimerListener.class, listener);
}
public coid removeTimerListener(TimerListener listener) {
listenerList.romve(TimerListener.class, listener);
}
//当从事件队列中移除事件对象.也就是要处理该事件对象时. 会调用事件源的processEvent方法.
//所以我们的事件源要实现processEvent方法. 这里我们从listenerList中得到TimerListener
//监听器对象的数组. 并调用每个监听器对象的timeElapsed方法.
public void processEvent(AWTEvent event) {
if (event instanceof TimerEvent) {
eventListener[] listeners = listenerList.getListeners(
TimerListener.class);
for (int i=0; i<listeners.length; i++)
((TimerListener)listeners[i]).timeElapsed((TimerEvent)event);
}
else super.processEvent(event);
}
}

//我们要向事件源注册监听器. 下边定义我们的监听器接口
interface TimerListener extends EventLister {
public void timeElapsed(TimerEvent event); //该接口中只声明一个方法
}

这样自定义事件需要的三个类都准备好了. 要使用上边的定时器事件. 可以如下:
Timer timer = new Timer(200);
timer.addTimerListener( new TimerListener() {
public void timeElapsed(TimerEvent event) {
//...
}
});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: