10.1 事件
10.1.2 事件机制
ActionScript. 3.0引入了单一事件处理模型,以替代以前各语言版本中存在的众多不同的事件处理机制。新的事件模型基于文档对象模型(DOM)第3级事件规范。虽然SWF文件格式并不专门遵循文档对象模型标准,但是显示列表和DOM结构之间存在的相似性足以使DOM事件模型的实现成为可能。
1.IEventDispatcher接口
IEventDispatcher接口是Flash Player内建的功能对象,负责实现事件模型。目前,ActionScript. 3.0使用IEventDispatcher接口处理有关事件的方法定义。
IEventDispatcher接口定义了5种方法:addEventListener、dispatchEvent、willTrigger、removeEventListener和hasEventListener。如表10-1所示:
表10-1 IEventDispatcher接口的方法
方法 | 功能 |
addEventListener | 注册事件监听器对象,使得事件监听器能够接收事件通知 |
dispatchEvent | 将事件调度到事件流中 |
willTrigger | 检查是否为指定事件类型注册了事件监听器 |
removeEventListener | 删除事件监听器 |
hasEventListener | 检查是否为特定事件类型注册了任何事件监听器 |
2.EventDispatcher类
在ActionScript. 3.0中,EventDispatcher类实现了IEventDispatcher接口。并且由于DisplayObject类是EventDispatcher类的派生类。因此,显示列表上的任何对象都可以使用IEventDispatcher接口的方法。
如果在自定义类中需要操作事件,最简单方法是扩展EventDispatcher类。这样就不需要自己编写IEventDispatcher接口的方法。如果自定义类必须继承其他类,则可以通过实现IEventDispatcher接口来操作事件。在实现IEventDispatcher接口时,必须创建EventDispatcher类中的成员,并处理事件的链接和传递等机制。
3.可视化的对象架构
在ActionScript. 2.0中,对象要具有派发事件的能力,必须经过特殊的功能扩展,否则无法使用事件模式,更谈不上事件监听。所以,为了实现事件模型,开发者需要自己动手,给现有对象进行扩展。到了ActionScript. 3.0中,所有可视化对象已经内建了事件机制。事件机制类的继承关系如图10-1所示。
从图10-1中可以看出,EventDispatcher类是DisplayObject类的基类,而DisplayObject类又是所有可视化元素的基类,通过类的继承关系,ActionScript. 3.0中的所有可视化对象都具有派发事件的功能。
Flex中也有类似的层级结构,UIComponent是所有可视化组件的基类,其继承关系如下所示:
UIComponent-->FlexSprite-->Sprite-->DisplayObjectContainer-->InteractiveObject-->DisplayObject
可以看出,UIComponent也继承DisplayObject类的内容,因此Flex中的所有组件都具备事件通信的所有功能。
10.1.3 事件流
ActionScript. 3.0的事件模型中新增加了事件流的概念。当一个事件发生,必然存在一个派发事件的对象,这里称之为目标对象。当事件发生后,Flash Player生成一个携带数据的对象,然后检查目标对象是否处在显示层中,如果是,则遍历从根容器一直到目标对象所在位置的所有对象。由于ActionScript. 3.0的显示层基于容器模式,这使得显示层类似一棵树,每个对象都是树上的一个节点。Flash Player自动检测所经过的节点是否注册了监听器。
事件流的作用是说明事件对象如何在显示列表中流动。显示列表以一种可以描述为树的层次结构形式进行组织。位于显示列表层次结构顶部的是舞台,它是一种特殊的显示对象容器,用作显示列表的根。舞台由flash.display.Stage类表示,且只能通过显示对象访问。每个显示对象都有一个名为stage的属性,该属性表示应用程序的舞台。
当Flash Player派发事件对象时,该事件对象进行一次从舞台到目标节点的往返行程。DOM Level3事件规范将目标节点定义为代表事件目标的节点。也就是说,目标节点是发生事件的显示列表对象。例如,如果用户单击名为“Child Node
事件流机制按照事件发生的先后顺序可以分为3个阶段,如下所示。
1) 捕获阶段 捕获事件capturing,从根节点开始顺序而下,检测每个节点是否注册了监听器。同时,Flex将事件对象的currentTarget值改为当前正在检测的对象。如果注册了监听器,则调用监听函数。
2) 目标阶段 检测目标的监听器targeting,触发在目标对象本身注册的监听程序
3) 冒泡阶段 事件冒泡bubbling,从目标节点到根节点,检测每个节点是否注册了监听器,如果有,则调用监听函数。
如果将显示列表看作是一个垂直的层次结构,其中舞台位于顶层(如图10-2所示),这样更容易理解事件流机制的三个阶段。如图10-3所示。
图10-2 显示列表结构
图10-3 事件流机制中的3个阶段
如果用户单击“Child Node
从该示例中可以看出,在捕获阶段中首次向下的行程包括Stage和Parent Node。在目标阶段中包括Child1 Node1花费的时间。冒泡阶段包括在向上返回到根节点的行程中遇到的Parent Node和Stage。
事件流的出现,使现在的事件处理系统与ActionScript早期版本事件处理系统相比,功能更为强大。早期版本的ActionScript中没有事件流,这意味着事件监听器只能添加到生成事件的对象。在ActionScript. 3.0中,不但可以将事件监听器添加到目标节点,还可以将其添加到事件流中的任何节点。
在用户界面组件包含多个对象时,沿事件流添加事件监听器的功能就显得十分有用。例如,按钮对象通常包含一个用作按钮标签的文本对象。如果无法将监听器添加到事件流中,则必须将监听器添加到按钮对象和文本对象,以确保收到有关在按钮上任何位置发生单击事件的通知。而事件流的存在则可以将一个事件监听器放在按钮对象上,以处理文本对象上发生的单击事件,或者按钮对象上未被文本对象遮住的区域上发生的单击事件。
不过,并非每个事件对象都参与事件流的所有三个阶段。例如enterFrame和initialize等,将直接交给相应的目标对象。有些事件可能以不在显示列表中的对象为目标,例如调度到Socket类的实例的事件。这些事件对象也将直接流至目标对象,而不参与捕获和冒泡阶段。
事件流的阶段划分不仅仅是概念的方便,还直接影响了事件监听器的行为。在向显示对象的addEventListener()方法中添加事件监听器时,可以设置useCapture参数,以确定监听器是运行于捕获阶段、目标阶段还是冒泡阶段。useCapture参数的取值和监听器运行的阶段如下所示:
l 如果将useCapture设置为true,则监听器只在捕获阶段处理事件,而不在目标或冒泡阶段处理事件。
l 如果useCapture为false,则监听器只在目标或冒泡阶段处理事件。
如果需要实现针对事件流三个阶段的事件响应,只能在代码中调用两次addEventListener(),第一次将useCapture设置为true,第二次再将useCapture设置为false。 |
10.2 事件对象
在Flex中,事件表现为事件对象。所有的事件对象必须直接或者间接继承flash.events.Event类。事件对象有两个主要用途:可以代表事件的属性和可用于影响事件处理系统的行为。本节主要介绍Event类的构造函数、属性和方法,并且介绍Event类的派生类。
10.2.1 Event类
事件本身也是对象,也是利用类进行定义。在ActionScript. 3.0中,所有的事件都以Event类为基类,例如MouseEvent和TimerEvent都是Event类的派生类。
1.创建Event对象
使用Event类,首先需要创建Event类的实例对象。Event的构造函数如下所示:
public function Event(type:String, bubbles:Boolean = false, cancelable:Boolean = false)
上述各参数说明如下:
l type 事件的类型。例如鼠标单击的事件类型为MouseEvent.CLICK。事件的类型可以通过Event.type获得。
l bubbles 该事件对象是否可以上浮。true表示可以上浮,false表示不可以上浮,默认为fasle。
l cancelable 该事件是否可以被取消。true表示可以取消。fasle表示不可以取消,默认为false。
例如:
var TestEvent:Event=new Event("Event.COMPLETE");
this.dispatchEvent(TestEvent);
在上述代码中,使用Event类的构造函数,创建了一个Event实例对象TestEvent,并且使用dispatchEvent()方法派发该事件。
在Event类的构造函数中,type参数是必选参数,其他两个参数是具有默认值,在创建Event对象时可以省略后面两个参数。 |
TAG:









