第5章 事件的发送和处理
事件处理系统是交互式程序设计的重要基础。利用事件处理机制,可以方便地相应用户输入和系统事件。ActionScript 3.0的事件机制基于文档对象模型(DOM3),是业界标准的事件处理体系结构。使用机制不仅方便,而且符合标准。ActionScript 3.0全新的事件处理机制是ActionScript编程语言中的重大改进,对ActionScript程序设计人员来说,在使用上也更加的方便和直观。
5.1 事件处理基础
本节将介绍事件和处理的基本概念,了解常见的事件处理任务。对照ActionScript编程语言中不同版本的事件处理机制的异同,明确ActionScript 3.0中事件处理机制具有良好的性能。
5.1.1 事件和事件处理基础知识
事件和事件处理是面向对象编程的基础。本小节将介绍事件和事件处理的基础知识以及事件处理的方法和事件处理的任务。
1. 事件和事件处理基本概念
在宏观的对象上,事件指的是当前所发生的事情。比如人,人要张口吃饭,张口是一个动作,也就是当前发生了一个张口事件,这个事件的结果是吃饭。编程语言中的事件,和宏观对象的事件类似,同样指当前程序所能接收到的当前所发生的事情。比如,现在单击了一下鼠标,也就是发生了单击鼠标这一状况,而这一状况就被称为发生了鼠标单击事件。
事件处理是指在发生了某个事件之后,需要怎么样来应对,下一步要做什么。还以“张口”这一事件为例,口张开了,下面将要发生的事情可能有多种,比如吃饭、呼吸等,那么需要有下一步的动作提示,才能继续下去,所以才有了张口吃饭这一完整的动作。同样,在发生了鼠标单击动作之后,需要指出下一步要做什么,是输出一段文字,还是开始播放一段动画,这就需要进行事件处理,实现在发生事件后下一步的动作。用于处理事件的函数或方法,习惯上称为事件侦听器或事件侦听函数。
张口吃饭,是因为感觉到了“张口”这一动作,才了解发生了这一事件。在编程的过程中,要了解当前是不是发生了事件,发生了什么事件,需要使用事件侦听来完成。事件侦听的目的就是为了了解当前有哪些事件发生,发生了什么状况。
张口吃饭,感觉到了“张口”这一动作,而这一感觉来自于神经系统,是对“口”进行神经分析的结果。与此类似,要知道程序中的某个对象发生了某个事件,就要给这个对象加上一个控制神经,即事件侦听,使得系统能够了解事件的发生。给对象添加事件侦听的过程,在编程语言中习惯称为在某个对象上注册某个事件侦听函数。
2. ActionScript 3.0中的事件和事件处理
ActionScript编程语言支持各种类型的交互操作,能够接受各种不同的事件。无论是响应鼠标单击、敲击键盘这些简单的操作,还是接受和处理文本框中输入的数据这样复杂的用户交互,与SWF文件进行的任何类型的交互操作都可以被视为事件。即使在没有用户操作的情况下也有可能发生事件。比如从后台加载完数据或者接受了一个远程的连接要求等。
在ActionScript 3.0中,每一个事件都用一个事件对象来表示。事件对象是Event(事件)类或者Event类的子类的实例。事件对象用于存储特定的事件信息,包含操作对象的方法。比如当Flash Player监测到用键盘操作时,就会创建一个KeyboardEvent(键盘事件)事件对象实例,用于记录该键盘操作事件。
创建事件对象后,Flash Player就会“调度”该事件对象,将该事件对象传递给作为事件目标的对象。比如Flash Player监听到键盘输入操作后,创建的事件对象就会被传递到对应的事件目标对象对事件进行处理。
在ActionScript 3.0中,可以通过事件侦听器来“侦听”代码中的事件对象。“事件侦听器”是用户自己编写的用于响应特定事件的函数或者方法。需要将事件侦听器添加到事件目标,或者添加到作为事件对象事件流的一部分显示对象列表,才能实现程序响应事件。比如要监听键盘操作的事件对象,需要实现把事件侦听器注册到Stage对象上。
编写事件侦听器代码的语法格式如下:
function事件侦听函数(事件对象:事件类型):void{ //此处是为响应事件而执行的动作 } 事件目标.addEventListener(事件对象的事件名称 事件侦听函数);
说明
此段代码执行两个操作,一是定义一个函数,指定为响应事件而执行的动作或者方法;另一个是为指定事件“注册”该函数,当该事件发生时,执行该函数的动作。
要创建自己的事件侦听器,需要注意以下格式说明。
❑事件侦听函数:指定响应事件要执行的动作或方法。
❑事件对象:要侦听的事件所调度的事件对象指定相应的类名称。
❑事件目标:被侦听的目标对象名称。
❑事件对象的事件名称:在事件对象类中具体的事件常量。
3. ActionScript 3.0中的事件处理任务
在ActionScript 3.0编程过程中,常见的使用事件处理的任务有:
❑编写代码以响应事件。
❑阻止代码响应事件。
❑处理事件对象。
❑处理事件流。
❑从类中调度事件。
❑创建自定义事件类型。
5.1.2 早期 ActionScript 版本中的事件处理
ActionScript 1.0使用on()和onClipEvent()两个事件处理函数来处理事件。具体包括:
❑on()事件处理函数,直接放在按钮或者影片剪辑实例上。
❑onClipEvent()处理函数,直接放在影片剪辑实例上。
这种方法把代码直接加在实例上,简单、方便、直接,但是由于分散在各个不同的元件之上,难以管理和维护。特别是处理不是本人编写的代码时,查看和找寻会浪费太多的宝贵时间。
在ActionScript 2.0中对事件处理进行了改进,增加了一些事件处理机制,具体为:
❑回调函数事件:onload、oninit、onComplete等。
❑事件侦听器:addListener()、addEventListener()。
特别是增加的事件侦听机制,已经实现了ActionScript 3.0的部分功能。但是在ActionScript 2.0中还存在着很多的不足,给开发人员造成了很大的困扰,比如下面的几个方面。
❑ActionScript 2.0中只有组件(UIComponent)类才有内置事件,其核心类和Flash API都没有内置事件。
❑事件侦听器的注册方式也有两种:一种是addListener();一种是addEventListener()。使用起来容易造成混淆。
❑ActionScript 2.0中关键字this的含义在各个事件处理系统中并不一致,造成this关键字指向不明确。
5.1.3 ActionScript 3.0中的事件处理
在ActionScript 3.0引入了基于文档对象模型(DOM3)唯一的一种事件处理模式,取代了以前各版本中存在的众多的事件处理机制。在ActionScript 3.0中只存在一种事件处理模型,虽然会对一些老版本的用户和一些非开发者造成一定的麻烦,但更加清晰,更加标准,更符合面向对象开发的需要。
对比ActionScript 2.0,ActionScript 3.0的事件处理体系具有以下几个新特点:
❑在ActionScript 3.0中,只能使用addEventListener()注册侦听器。
❑在ActionScript 3.0中,可以对属于事件流部分的任何对象调用addEventListener()方法。
❑在ActionScript 3.0中,只有函数或方法可以是事件侦听器。
5.2 Event类
在ActionScript 3.0的事件处理系统中,事件对象主要有两个作用:一是将事件信息储存在一组属性中,来代表具体事件;二是包含一组方法,用于操作事件对象和影响事件处理系统的行为。
ActionScript 3.0中,在Flash播放器的应用程序接口中,有一个Event类,作为所有事件对象的基类,也就是说,程序中所发生的事件都必须是Event类或者其子类的实例。
5.2.1 了解Event类的属性
Event类公开的属性有type、cancelable、target、currentTarget、eventphase、bubles。
1. type属性
每个事件对象都有关联的事件类型。事件类型存储以字符串的形式存储在Event.type属性中。利用事件类型,可以区分不同类型的事件。比如下面的代码说明给clickHandler()侦听器函数响应传递给myobj的任何鼠标单击事件对象。
myobj.addEventListener(MouseEvent.CLICK,clickHandler);
事件类型与Event类自身关联并由Event类常数表示,在Event类中存在二十多种事件类型常量。利用这些常数可以引用特定的事件类型,使用时要使用这些常数而不是它所代表的字符串。如果在使用时输入了错误的常数名称,编译器会报错。但是如果不使用常量而使用字符串,编译时可能不会提示错误名称,而可能会导致难以调试的意外情况。比如添加事件侦听器时,请使用以下代码:
myobj. addEventListener(MouseEvent.CLICK,clickHandler);
而不是ActionScript 2.0中的代码:
myobj. addEventListener("click", clickHandler);
注意 事件的类型是区分大小写的。
2. cancelable属性
事件的默认行为是否可以被阻止由布尔值表示,并存储在Event.cancelable属性中。此属性是一个布尔值,默认为false。这个属性一般是和preventDefault()方法结合在一起使用的。
3. target属性
target属性用于存储对事件目标的引用。下面先生成一个显示(sprite)对象sp,然后给其注册一个鼠标单击事件,单击之后,使用target属性实现对显示对象的引用,并使sp的位置发生改变。代码如下所示:
//定义一个变量,使用绘图对象创建一个圆 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); //把圆加入舞台中 addChild(sp); //创建事件侦听函数 function TestTar(event:MouseEvent):void { //通过获取目标,跳转对象位置 event.target.x=300; event.target.y=100; } //注册事件侦听 sp.addEventListener(MouseEvent.CLICK,TestTar);
完成后的效果如图5.1所示。
图5.1 事件目标效果图
4. 其他属性
currentTarget、eventphase和bubbles这3个属性都和ActionScript 3.0的事件流机制有关,在平时用到的不多。
要注意的是,实例属性全部是只读属性[read-only]。这些属性是使用getter方法实现的,并不是真正的实例属性。
Event类还有26个静态字符串常量,定义了26种事件类型。其中包括:“ADDED”表示对象被添加到显示列表时发送事件;“REMOVED”表示对象从显示列表被移除时发送事件;“UNLOAD”表示对象被卸载时发送事件。
5.2.2 了解Event类的方法
Event类的方法有7种:clone()、toString()、stopPropogation()、stopImmediatePropogation()、preventDefault()、isDefaultPrevented()和formatToString()。这些方法的用途如下:
❑Event.clone()方法用于赋值Event子类实例,返回Event对象原始实例的副本。当需要自定义Event子类时,就必须要继承Event.clone()方法,用于赋值自定义类的属性。另外还要加上新的属性,否则在侦听器重写调用时,这些属性的值会出现错误。
❑Event.toString()属性返回一个包含Event对象的所有属性的字符串。如果要自定义事件类,那么重写toString()方法时,可以使用formatToString()这个方法在返回的字符串中加入新的事件实例属性。
❑Event.stopPropogation()方法可阻止事件对象移动到下一个节点,但只有在允许执行当前节点上的任何其他事件侦听器之后才起作用。
❑Event.stopImmediatePropogation()方法也阻止事件对象移动到下一个节点,但不允许执行当前节点上的任何其他事件侦听器。
❑Event.preventDefault()、Event.isDefaultPrevented()和Event.cancelable属性结合使用,用于取消事件的默认行为的发生。
5.2.3 Event类的子类
对于很多事件来说,使用Event类的一组属性就已经足够了。但是,Event类中的属性无法捕获其他事件具有的独特的特性,比如鼠标的单击事件、键盘的输入事件等。ActionScript 3.0的应用程序接口特意为这些具有显式特征的事件准备了Event类的几个子类。这些子类主要包括:
❑鼠标类:MouseEvent。
❑键盘类:KeyBoardEvent。
❑时间类:TimerEvent。
❑文本类:TextEvent。
每个子类定义了对于该种事件类别来说唯一的附加属性和事件类型。比如,与鼠标输入相关的事件具有若干独特的特性,无法被Event类中定义的属性捕获。MouseEvent类则添加了10个属性,扩展了Event类。这10个属性包含诸如鼠标事件的位置和在鼠标事件过程中是否按下了特定键等信息。
Event子类还增加了代表与子类关联的事件类型的常量。例如,MouseEvent类定义几种鼠标事件类型的内容,包括click、doubleClick、mouseDown和mouseUp事件类型。
当然,有时可能需要在事件对象中加入额外的属性或方法时,这就需要自定义事件类。
关于这些子类的用法,后面的章节会逐步讲述。
5.3 事件侦听器
事件侦听器也就是以前版本中的事件处理函数,是事件的处理者,负责接收事件携带的信息,并在接收到该事件之后执行事件处理函数体内的代码。
添加事件侦听的过程有两步:第一步是创建一个事件侦听函数;第二步是使用addEventListener()方法在事件目标或者任何显示对象上注册侦听器函数。
5.3.1 创建事件侦听器
事件侦听器必须是函数类型,可以是一个自定义的函数,也可以是实例的一个方法。创建侦听器的语法格式如下:
function 侦听器名称(evt:事件类型):void{...}
语法格式说明如下:
❑侦听器名称:要定义的事件侦听器的名称,命名需符合变量命名规则。
❑evt:事件侦听器参数,为必需。
❑事件类型:Event类实例或其子类的实例。
❑void:返回值必须为空,不可省略。
下面代码创建一个显示红色圆形的简单SWF文件,并使用名为Test()的侦听器函数侦听红色圆形上的鼠标单击事件。代码如下所示:
//定义一个变量,使用绘图对象创建一个圆 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); //把圆加入舞台中 addChild(sp); //创建事件侦听函数 function Test(event:MouseEvent):void { trace("事件侦听函数建立成功!") } //注册事件侦听器 sp.addEventListener(MouseEvent.CLICK,Test);
说明
在显示的红色圆形上单击鼠标,输出为“事件侦听函数建立成功!”,说明事件侦听器建立成功。
完成后的效果如图5.2所示。
图5.2 注册事件侦听测试
ActionScript 3.0主要是面向对象的编程而设计,所以事件侦听函数同样可以为类方法。把代码写成文档类可以实现相同的效果。代码如下所示:
//创建包 package Lzxt { //导入包Sprite import flash.display.Sprite; //创建类 public class Test extends Sprite { //构造函数 public function Test() { //创建对象 var sp:Csp = new Csp(); //加入对象 addChild(sp); } } } //包外类,用于创建对象 import flash.display.Sprite; import flash.events.MouseEvent; class Csp extends Sprite { public function Csp() { //使用绘制方法绘制圆形 graphics.beginFill(0xFF0000); graphics.drawCircle(100,100,40); graphics.endFill(); //至此事件侦听 addEventListener(MouseEvent.CLICK, testclick); } //创建事件侦听函数 private function testclick(event:MouseEvent):void { trace("类方法实现事件处理函数"); } }
说明
在显示的红色圆形上单击鼠标,输出为“类方法实现事件处理函数”,说明事件侦听器建立成功。
完成后的效果如图5.3所示。
图5.3 类方法实现事件侦听效果
5.3.2 管理事件侦听器
在ActionScript 3.0中使用IEventDispatcher接口的方法来管理侦听器函数,主要用于注册、检查和删除事件侦听器。
1. 注册事件侦听器
addEventListener()函数用来注册事件侦听函数。注册侦听器的语法格式如下:
事件发送者.addEventListener(事件类型,侦听器);
语法格式说明如下:
❑事件发送者:其必须为EventDispatcher类或子类的实例。
❑事件类型:Event类实例或其子类的实例。
❑侦听器:事件执行时的侦听器函数,注意,此数的函数不要函数名后的括号。
下面代码示例把Test()函数注册为sp对象的侦听器,接收鼠标单击事件:
sp.addEventListener(MouseEvent.CLICK,Test);
注意下面的注册语句是错误的:
sp.addEventListener(MouseEvent.CLICK,Test());
2. 删除事件侦听器
removeEventListener()函数用来删除事件侦听器函数。删除侦听器的语法格式如下:
事件发送者.removeEventListener(事件类型,侦听器);
事件发送者、事件类型和侦听器的要求与注册事件侦听器的要求相同,不再赘述。
将不再使用的所有侦听器删除可以节约系统资源,提高程序效率。下面代码创建一个显示红色圆形的简单SWF文件。名为Test()的侦听器函数侦听红色圆形上的鼠标单击事件,当单击之后,删除事件侦听器。代码如下所示:
//定义一个变量,使用绘图对象创建一个圆 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); //把圆加入舞台中 addChild(sp); //创建事件侦听函数 function Test(event:MouseEvent):void { trace("事件侦听函数建立成功!") //移除事件侦听函数 sp.removeEventListener(MouseEvent.CLICK,Test); } //注册事件侦听函数 sp.addEventListener(MouseEvent.CLICK,Test);
说明
在显示的红色圆形上单击鼠标,输出为“事件侦听函数建立成功!”,说明事件侦听器建立成功,再次单击,没有任何输出,说明事件侦听器已经被删除。
3. 检查事件侦听器
HasEventListener()方法和willTragger()方法,都可以用来检测当前的事件发送者注册了何种事件类型的侦听器。
检查事件侦听器语法格式如下:
事件发送者.hasEventListener(事件类型);
继续使用上面的效果,在鼠标单击红色圆形之前检查一次事件侦听器,并在单击之后再检查一次事件侦听器。代码如下所示:
//定义一个变量,使用绘图对象创建一个圆 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); //把圆加入舞台中 addChild(sp); //创建事件侦听函数 function Test(event:MouseEvent):void { trace("事件侦听函数建立成功!"); //移除事件侦听 sp.removeEventListener(MouseEvent.CLICK,Test); trace(sp.hasEventListener(MouseEvent.CLICK)); } //注册事件侦听 sp.addEventListener(MouseEvent.CLICK,Test); trace(sp.hasEventListener(MouseEvent.CLICK));
代码执行后的输出结果如下所示:
true
事件侦听函数建立成功!
false
说明
从输出结果可以看出,在删除事件侦听器之前,该事件存在,输出为true,当删除之后,输出为false。
willTrigger()方法同样也可以检查事件侦听器。willTrigger()不但会检查该显示对象上的侦听器,还会检查该显示列表对象在事件流所有阶段中的所有父级上的侦听器。
下面的代码先建立一个红色的圆形,然后在红色圆形中建立一个黄色的小圆形,名为Test()的侦听器函数侦听红色圆形上的鼠标单击事件,最后检查黄色圆形上的事件侦听器。代码如下所示:
//定义一个变量,使用绘图对象创建一个圆 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); //把圆加入舞台中 addChild(sp); //创建另一个对象 var spp:Sprite=new Sprite(); spp.graphics.beginFill(0xffff00); spp.graphics.drawCircle(100,100,20); spp.graphics.endFill(); sp.addChild(spp); //创建事件侦听函数 function Test(event:MouseEvent):void { trace("事件侦听函数建立成功!"); } //注册事件侦听函数 sp.addEventListener(MouseEvent.CLICK,Test); trace(spp.hasEventListener(MouseEvent.CLICK)); trace(spp.willTrigger(MouseEvent.CLICK)); /* 输出为: false true */
说明
输出的结果可以说明hasEventListener()方法只能检测指定的显示对象上的事件侦听器,而willTrigger()方法还可以检查该显示对象父级上的显示对象。
5.4 事件处理类型
ActionScript 3.0使用单一事件模式来管理事件,所有的事件都位于flash.events包内,其中构建了二十多个Event类的子类,用来管理相关的事件类型。本节介绍常用的鼠标事件(MouseEvent)类型、键盘事件(KeyboardEvent)类型和时间事件(TimerEvent)类型和帧循环(ENTER_FRAME)事件。
5.4.1 鼠标事件
在ActionScript 3.0之前的语言版本中,常常使用on(press)或者onClipEvent(mousedown)等方法来处理鼠标事件。而在ActionScript 3.0中,统一使用MouseEvent类来管理鼠标事件。在使用过程中,无论是按钮还是影片事件,统一使用addEventListener注册鼠标事件。此外,若在类中定义鼠标事件,则需要先引入(import)flash.events.MouseEvent类。
MouseEvent类定义了10种常见的鼠标事件,具体如下:
❑CLICK:定义鼠标单击事件。
❑DOUBLE_CLICK:定义鼠标双击事件。
❑MOUSE_DOWN:定义鼠标按下事件。
❑MOUSE_MOVE:定义鼠标移动事件。
❑MOUSE_OUT:定义鼠标移出事件。
❑MOUSE_OVER:定义鼠标移过事件。
❑MOUSE_UP:定义鼠标提起事件。
❑MOUSE_WHEEL:定义鼠标滚轴滚动触发事件。
❑ROLL_OUT:定义鼠标滑入事件。
❑ROLL_OVER:定义鼠标滑出事件。
下面通过几个范例来说明这些鼠标事件的使用方法,并解决从ActionScript 2.0到ActionScript 3.0过程中一些原有实现方法的转换。
范例一:给显示对象添加鼠标单击事件
下面先建立一个简单按钮,把名为click的事件侦听器注册到按钮上,执行鼠标单击事件,按钮上的文字提示“你单击了按钮”。代码如下所示:
//创建矩形作为按钮背景 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawRect(0,0,100,20); sp.graphics.endFill(); addChild(sp); //创建按钮上的文本 var label:TextField=new TextField(); label.text="单击按钮"; sp.addChild(label); //创建单击事件处理函数 function click(event:MouseEvent):void { //单击后改变的文字内容 label.text="你单击了按钮"; } //注册鼠标单击事件 sp.addEventListener(MouseEvent.CLICK,click);
完成后的效果如图5.4所示。
图5.4 单击效果图
范例二:给显示对象添加鼠标双击事件
鼠标双击事件和单击事件的使用方法相同,但是,系统默认鼠标双击事件并没有打开,需要把鼠标双击属性(double-ClickEnabled)打开,否则即使执行了双击操作,按钮也不会响应操作。
下面同样建立一个简单按钮,把名为dbclick的事件侦听器注册到按钮上,双击按钮,按钮上的文字变为“你双击了按钮”。代码如下所示:
//创建按钮背景 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawRect(0,0,100,20); sp.graphics.endFill(); addChild(sp); //要执行双击事件,必须将其属性设置为true sp.doubleClickEnabled = true; //创建按钮上文字 var label:TextField=new TextField(); label.text="双击按钮"; label.doubleClickEnabled=true; sp.addChild(label); //创建双击事件处理函数 function dbclick(event:MouseEvent):void { label.text="你双击了按钮"; } //注册双击事件侦听器 sp.addEventListener(MouseEvent.DOUBLE_CLICK,dbclick);
完成后的效果如图5.5所示。
图5.5 双击效果图
范例三:创建一个可以拖放的显示对象
先创建一个圆形的显示对象,然后把press事件侦听器注册给MouseEvent. MOUSE_DOWN事件,把release事件侦听器注册给MouseEvent.MOUSE_UP,实现在显示对象上按下鼠标可以拖动,释放鼠标后停止拖动效果。代码如下所示:
//创建圆形作为拖放对象 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); addChild(sp); //设置圆形可以接受按钮事件 sp.buttonMode=true; //创建拖动函数 function press(evt:MouseEvent):void { //执行拖动 evt.target.startDrag(); } //创建停止拖动函数 function release(evt:MouseEvent):void { evt.target.stopDrag(); } //注册鼠标按下事件 sp.addEventListener(MouseEvent.MOUSE_DOWN,press); //注册鼠标松开时事件 sp.addEventListener(MouseEvent.MOUSE_UP,release);
完成后的效果如图5.6所示。
图5.6 拖动效果图
范例四:自定义的鼠标样式
创建一个自定义的鼠标形状,然后把move事件注册给MouseEvent.MOUSE_MOVE事件。注意,事件的发送者是舞台stage对象而不是创建的鼠标样式。代码如下所示:
var cursor:Sprite=new Sprite(); cursor.graphics.lineStyle(1,0x00ff00,1); cursor.graphics.moveTo(0,0); cursor.graphics.lineTo(15,8); cursor.graphics.lineTo(9,16); cursor.graphics.lineTo(0,13); cursor.graphics.lineTo(0,0); addChild(cursor); //以上创建鼠标样式 function move(evt:MouseEvent):void { 鼠标样式跟随 cursor.x=evt.stageX; cursor.y=evt.stageY; evt.updateAfterEvent(); } //创建move事件侦听函数 stage.addEventListener(MouseEvent.MOUSE_MOVE,move);//注册鼠标事件 // Mouse.hide()函数控制鼠标隐藏 Mouse.hide();
完成后的效果如图5.7所示。
图5.7 自定义鼠标样式效果图
范例五:鼠标指针划过时产生变色效果
创建一个圆形显示对象,把makeBlue事件侦听器注册给MouseEvent.ROLL_OVER事件,把makeRed事件侦听器注册给MouseEvent.ROLL_OUT事件。实现鼠标指针滑过对象时显示蓝色,滑出对象时显示红色的效果。代码如下所示:
//创建对象实例 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); addChild(sp); // 创建与sp关联的 ColorTransform 实例 var colorInfo:ColorTransform = sp.transform.colorTransform; //创建makeBlue事件侦听器 function makeBlue(event:MouseEvent):void { // 设置 ColorTransform 对象的颜色 colorInfo.color = 0x003399; // 将更改应用于显示对象 event.target.transform.colorTransform = colorInfo; } function makeRed(event:MouseEvent):void { // 设置 ColorTransform 对象的颜色 colorInfo.color = 0xFF0000; // 将更改应用于显示对象 event.target.transform.colorTransform = colorInfo; } sp.addEventListener(MouseEvent.ROLL_OVER,makeBlue); sp.addEventListener(MouseEvent.ROLL_OUT,makeRed); //注册事件
完成后的效果如图5.8所示。
图5.8 变色效果图
上面的范例介绍了常用的鼠标操作事件,由于其他的鼠标事件不大常用,在这里不再给出范例。
5.4.2 键盘事件
键盘操作也是Flash用户交互操作的重要事件。在ActionScript 3.0中使用KeyboardEvent类来处理键盘操作事件。它有两种类型的键盘事件:KeyboardEvent.KEY_DOWN和KeyboardEvent.KEY_UP。
❑KeyboardEvent.KEY_DOWN:定义按下键盘时事件。
❑KeyboardEvent.KEY_UP:定义松开键盘时事件。
注意 在使用键盘事件时,要先获得它的焦点,如果不想指定焦点,可以直接把stage作为侦听的目标。
下面定义一个显示对象,把keydown侦听器注册给KeyboardEvent.KEY_DOWN事件,把keyup侦听器注册给KeyboardEvent.KEY_UP事件,实现按下键盘时显示对象显示文字“你按了键盘”,松开键盘上的键时显示对象显示文字“你现在松开了按下的键”。代码如下所示:
//创建矩形对象 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawRect(0,0,100,20); sp.graphics.endFill(); addChild(sp); //创建显示文本对象 var label:TextField=new TextField(); label.text=""; sp.addChild(label); //按下键盘事件处理函数 function keydown(event:KeyboardEvent):void { label.text="你按了键盘"; } //松开键盘事件处理函数 function keyup(event:KeyboardEvent):void { label.text="你现在松开了按下的键"; } //注册事件侦听 stage.addEventListener(KeyboardEvent.KEY_DOWN,keydown); stage.addEventListener(KeyboardEvent.KEY_UP,keyup);
注意 因为在使用时要获得焦点,所以要先用鼠标左键单击一下显示对象,然后按下键盘。
完成后的效果如图5.9所示。
图5.9 按键测试效果图
在ActionScript 2.0中,使用key类取得一些键的操作事件,比如Key.ENTER、Key.LEFT等,使用key.getcode()方法来获取按下的键值。在ActionScript 3.0中同样可以进行这些事件操作,不过这些属性和方法变为Keyboard.DOWN、Keyboard.UP等,而Key.getCode变为了keyCode。keyCode会返回正在按下或释放的键的键控代码值。
下面的示例创建一个显示对象,并且使用上下左右键控制其简单运动。代码如下所示:
var box=new Sprite(); addChild(box); box.graphics.beginFill(0xff0000); box.graphics.drawRect(0,0,40,40); box.graphics.endFill(); box.x=stage.stageWidth / 2; box.y=stage.stageHeight / 2; //建立显示对象box stage.addEventListener(KeyboardEvent.KEY_DOWN,keyevt); //在舞台上注册键盘按下事件 //建立事件侦听器 function keyevt(event:KeyboardEvent):void { switch (event.keyCode) { //获取当前键盘代码 case Keyboard.UP: //按下向上键 box.y-= 10; break; case Keyboard.DOWN: //按下向下键 box.y+= 10; break; case Keyboard.LEFT: //按下向左键 box.x-= 10; break; case Keyboard.RIGHT: //按下向右键 box.x+= 10; break; default: break; } }
完成后的效果如图5.10所示。
图5.10 键盘控制显示对象效果图
要使用键盘进行操作,触发相关事件,最好使用Keyboard类提供的预定义常量值来引用相应的keyCode属性,而不是键控代码。因为键和键控代码之间的对应关系取决于设备和操作系统。当然也可以通过键控代码来触发事件。比如上面的示例把上、下、左、右4个键换为W、S、A、D4个键,代码如下所示:
var box=new Sprite(); addChild(box); box.graphics.beginFill(0xff0000); box.graphics.drawRect(0,0,40,40); box.graphics.endFill(); box.x=stage.stageWidth / 2; box.y=stage.stageHeight / 2; //建立显示对象box //在舞台上注册键盘按下事件 stage.addEventListener(KeyboardEvent.KEY_DOWN,keyevt); //建立事件侦听器 function keyevt(event:KeyboardEvent):void { //获取当前键盘代码 switch (event.keyCode) { case 87: //按下W键 box.y-= 10; break; case 83: //按下S键 box.y+= 10; break; case 65: //按下A键 box.x-= 10; break; case 68: //按下D键 box.x+= 10; break; default: break; } }
5.4.3 时间事件
在ActionScript 3.0中使用Timer类取代ActionScript之前版本中的setinterval()函数,而执行对Timer类调用的事件进行管理的是TimerEvent事件类。要注意的是,Timer类建立的事件间隔要受到SWF文件的帧频和Flash Player的工作环境(比如计算机的内存的大小)的影响,会导致计算不准确。
Timer类有两个事件:
❑TimerEvent.TIMER:计时事件,按照设定的事件发出。
❑TimerEvent.TIMER_COMPLETE:计时结束事件,当计时结束时发出。
下面的示例建立一个简单的1分钟倒计时效果,代码如下所示:
//创建一个文本框,用于显示时间 var label:TextField=new TextField(); addChild(label); //以上建立一个文本框用于显示倒计时时刻 var myTimer:Timer = new Timer(1000,60); //以1秒为间隔,触发60次动作 myTimer.addEventListener(TimerEvent.TIMER, timefun); //把timefun事件侦听器注册给TimerEvent.TIMER事件 myTimer.start(); //开始计时 var time:Number=60; //倒计时时间 //显示当前时间 label.text=String(time); //创建事件侦听器 function timefun(the:TimerEvent):void { //记录次数递减 time-=1; //显示次数 label.text=String(time); }
完成后的效果如图5.11所示。
图5.11 倒计时效果图
5.4.4 帧循环ENTER_FRAME事件
帧循环ENTER_FRAME事件是ActionScript 3.0中动画编程的核心事件。该事件能够控制代码跟随Flash的帧频播放,在每次刷新屏幕时改变显示对象。
使用该事件时,需要把该事件代码写入事件侦听函数中,然后在每次刷新屏幕时,都会调用Event. ENTER_FRAME事件,从而实现动画效果。
下面使用该事件创建一个简单的动画:在屏幕中创建一个ball,每次刷新屏幕时,让ball的x属性增加一点,直到超出屏幕区域时返回左边继续,这样就形成了连续的动画效果。代码如下所示:
//创建ball对象 var ball:Sprite=new Sprite(); ball.graphics.beginFill(0xff0000); ball.graphics.drawCircle(0,0,10); ball.graphics.endFill(); //加入舞台 addChild(ball); //设置初始位置 ball.x=50; ball.y=200; //创建事件侦听函数 function moveball(evt:Event):void { //改变位置 ball.x++; } //注册事件 ball.addEventListener(Event.ENTER_FRAME,moveball);
注意
在使用帧循环ENTER_FRAME事件时,由于该循环一旦被执行,就会不断地刷新屏幕,所以如果不需要动画,或不需要侦听该事件时,一定要移除该侦听。由于侦听此类事件将消耗大量的系统资源,所以一定要及时删除。
5.5 练习题
1. 简述addEventListener函数的5个参数的含义,以及强引用和弱引用的区别。
2. 简述AS 3.0的事件机制。
3. 下列关于TimerEvent和ENTER_FRAME事件描述正确的是( )。
A. Timer计时器的时间间隔是准确的,不受Flash Player运行程序时的速度影响
B. ENTER_FRAME事件以帧频速率响应
C. Timer时间间隔单位为秒
D. Timer计时结束时,会自动删除TimerEvent. TIMER时间
4. 如何自定义一个带参数的事件并广播?
5. 思考一下,鼠标事件中的MOUSE_OVER和ROLL_OVER有什么异同点。