智慧 + 毅力 = 无所不能

正确性、健壮性、可靠性、效率、易用性、可读性、可复用性、兼容性、可移植性...

导航

自定义事件和自定义事件类

Posted on 2009-12-02 16:17  Bill Yuan  阅读(866)  评论(0编辑  收藏  举报

正确区分自定义事件和自定义事件类,如果你只是简单地发送一个你自己的事件而不需要更多信息,可以使用

 

var myInfo:Event=new Event("myOwnEvent");
dispatchEvent(myInfo)

 

来实现,我们看到自定义事件很简单,只需给Event类传入一个特殊的不与内置事件类型重复的字符串即可
    可以做如下测试:
代码
//outer
var outer = new Sprite();
outer.name
="Outer";
outer.graphics.beginFill(
0xFF0000);
outer.graphics.drawRect(
0,0,100,100);
//mid
var mid = new Sprite();
mid.name
="mid"
mid.graphics.beginFill(
0x00FF00);
mid.graphics.drawRect(
0,0,50,50);
//inner
var inner = new Sprite();
inner.name
="inner";
inner.graphics.beginFill(
0x0000FF);
inner.graphics.drawRect(
0,0,25,25);
//addChild
outer.addChild(mid);
mid.addChild(inner);
addChild(outer);
outer.x
=outer.y=100;
//添加侦听器
outer.addEventListener("myOwnEvent",myOwnEventHandler,true);//注意此处将useCapture设为true所以会在捕获阶段调用侦听器
mid.addEventListener("myOwnEvent",myOwnEventHandler,true);//同上
inner.addEventListener("myOwnEvent",myOwnEventHandler);
function myOwnEventHandler(evt){
        trace(
"事件流当前阶段:"+evt.eventPhase)
        trace(
"鼠标点击处最内层的显示对象(target)是:" + evt.target.name)
        trace(
"事件当前流经显示对象(currentTarget)是:"+evt.currentTarget.name)
        trace(
"===============================================================")
   
}
var myInfo
=new Event("myOwnEvent")
inner.dispatchEvent(myInfo)
//由inner向FlashPlayer提出请求把一个myOwnEvent的事件对象加入事件流

 

 

输出
事件流当前阶段:1
鼠标点击处最内层的显示对象(target)是:inner
事件当前流经显示对象(currentTarget)是:Outer
===============================================================
事件流当前阶段:1
鼠标点击处最内层的显示对象(target)是:inner
事件当前流经显示对象(currentTarget)是:mid
===============================================================
事件流当前阶段:2
鼠标点击处最内层的显示对象(target)是:inner
事件当前流经显示对象(currentTarget)是:inner
===============================================================
可以看到我们自定义的事件被加入到了事件流中并且被outer,mid,inner收到了
这里要补充一点,dispatchEvnet的调用对象将会被作为事件的目标对象(target)
晕了没?
你可以修改一下上面的代码来帮助你理解
代码:
var myInfo=new Event("myOwnEvent")
trace(myInfo.target)
//输出调用dispatchEvent方法前的target的名字,输出结果是null
inner.dispatchEvent(myInfo)
trace(myInfo.target.name)
//输出调用dispatchEvent方法前的target的名字,输出结果是inner

 

 

如果你认真看完了上面的文字,你应该对自定义事件有了一定了解,在一般情况下,这种方法已经够用了,如果你还需要更复杂的事件的话,你就可以考虑创建你自己的事件类

编写自己的事件类
   在上面的Mp3播放器例子中我们提到了给Mp3播放控制部分发送一个ProgressChangeEvent事件,现在继续
   给它发送这个事件的目标是要让它知道播放进度改变了,还要让它知道进度变成了多少,这就是参数progressBar.progress的作用
自定义事件类
代码
package
{
    
import flash.events.Event;
    
    
public class ProgressChangeEvent extends Event
    {
        
static private const PROGRESS_CHANGE = "progresschange"//是不是跟MouseEvent.MOUSE_DOWN长得很像,其实MouseEvent差不多也是这么写出来的
        public var position:Number = 0//这是我们新加的变量,用来存储进度信息。

        
public function ProgressChangeEvent(pos:Numbre)
        {
            
super(PROGRESS_CHANGE); //调用父类的构造函数,将PROGRESS_CHANGE设置为默认事件类型
            position = pos;
        }

        
public override function clone():Event //你应负责任地重写clone方法
        {
            var cloneEvent 
= new ProgressEvent();
            cloneEvent.position 
= this.position;
            
return cloneEvent;
        }

        
public override function toString():String //你应负责任地重写toStrin方法
        {
            
return formatToString("ProgressChangeEvent""type""bubbles""cancelable""eventPhase""position");
        }

    }

}

 

 

一个修秀的程序员应该在自定义类中重写clone和toString方法,不论你是否会用到这两个方法!!因为在调用dispatchEvent(myInfo)时实际是把myInfo对象的一个拷贝给了dispatchEvent方法。
-_-!!终于写完了,现在我们可以使用自己写的事件类了。
把上面的代码保存成ProgressChangeEvent.as文件,然后在同一目录下新建一个fla文件F9打开动作面板输入:

代码:

代码
import ProgressChangeEvent//其实可以省略,因为在同一目录下

//PlayerContralCenter
var PlayerContralCenter=new Sprite();
PlayerContralCenter.name
="PlayerContralCenter"
PlayerContralCenter.graphics.beginFill(
0x00FF00);
PlayerContralCenter.graphics.drawRect(
0,0,100,100);
//progressBar
var progressBar=new Sprite();
progressBar.name
="progressBar"
progressBar.graphics.beginFill(
0xFF0000);
progressBar.graphics.drawRect(
0,0,100,5);
//addChild
PlayerContralCenter.addChild(progressBar);
addChild(PlayerContralCenter);
progressBar.y
=50
PlayerContralCenter.x
=PlayerContralCenter.y=100

//PlayerContralCenter侦听ProgressChangeEvent事件,将useCapture设置为true的原因是我们的自定义事件类是不冒泡的(你也可以修改成可冒泡的),所以必须在捕获阶段响应
PlayerContralCenter.addEventListener(ProgressChangeEvent.PROGRESS_CHANGE,handler,true);
progressBar.addEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler);


function handler(evt:ProgressChangeEvent){
    trace(
"我是"+evt.currentTarget.name+",我收到了"+evt.type+"事件,"+"事件信息是"+evt.position);
}
function mouseDownHandler(evt:MouseEvent){
        var pos
=evt.target.mouseX/evt.target.width;
    progressBar.dispatchEvent(
new ProgressChangeEvent(pos));
}

 

 

输出
我是PlayerContralCenter,我收到了progresschange事件,事件信息是0.42
我是PlayerContralCenter,我收到了progresschange事件,事件信息是0.84
我是PlayerContralCenter,我收到了progresschange事件,事件信息是0.94
我是PlayerContralCenter,我收到了progresschange事件,事件信息是0.97
我是PlayerContralCenter,我收到了progresschange事件,事件信息是0.05
.............