您的位置: 首页 > 技术文档 > 多媒体制作 > [AS2]事件处理机制
微软 Silverlight 入门简介 回到列表 Flash处理外部XML文档数据
 [AS2]事件处理机制

作者:chooseflash 时间: 2007-07-13 文档类型:原创 来自:蓝色理想

第 1 页 [AS2]事件处理机制 -- 目录
第 2 页 [AS2]事件处理机制 -- 事件处理机制
第 3 页 [AS2]事件处理机制 -- 创建类库
第 4 页 [AS2]事件处理机制 -- 使用回调函数
第 5 页 [AS2]事件处理机制 -- 使用addListener方法 一
第 6 页 [AS2]事件处理机制 -- 使用addListener方法 二
第 7 页 [AS2]事件处理机制 -- 建立强大的事件处理机制
第 8 页 [AS2]事件处理机制 -- 小结

[6.建立强大的事件处理机制]

这一节讲建立强大的事件处理机制.学完这节,如果有接触过 AS3 的,马上会想到一句:这不就是 AS3 的事件处理机制吗?
的确.可以说跟 AS3 的事件处理机制一模一样.但还是有个作用域的问题.这节对想学习 AS3 的事件处理机制会有很大
帮助.如果你掌握这节中的内容,在 AS3 中就只有语法问题.也就会很快进入状态.毕竟是"水往低处流,人往高处走".对现
在用 AS2 的,学 AS3 是迟早的问题.不过 AS2 在新版本出来之前还是会很有用的(个人的看法).

作用域因为一样,前面也讲过,这里就不在啰嗦.
事件对象.这里已经创建一个 Event 类(或其子类)来代替.但功能一样.

这节讲的事件处理机制的形态(代码).
发送事件:

//继承.
import AS2.events.Event;
import AS2.events.CFEventDispatcher;
class className extends CFEventDispatcher
{
    ...
    this.dispatchEvent(new Event(Event.COMPLETE));
    ...
}

//不继承.
import AS2.events.Event;
import AS2.events.CFEventDispatcher;
class className
{
    public var addEventListener:Function;
    public var removeEventListener:Function;
    private var dispatchEvent:Function;
   
    public function className()
    {
        //此方法要在使用 dispatchEvent 方法前被执行.一般放于构造函数中.
        CFEventDispatcher.initialize(this);
    }
   
    ...
    this.dispatchEvent(new Event(Event.COMPLETE));
    ...
}

侦听事件:

//使用自定义函数.
import AS2.events.Event;
import className;
...
var cn:className = new className();
//自定义函数.
function completeHandler(evt:Event):Void
{
    trace(this); //输出: _level0.cn
}
cn.addEventListener(Event.COMPLETE, completeHandler);
...

//使用事件侦听器对象.
import AS2.events.Event;
import className;
...
var cn:className = new className();
//事件同名函数.
function complete(evt:Event):Void
{
    trace(this); //输出: this(指向侦听器对象)
}
cn.addEventListener(Event.COMPLETE, this);
...

移除侦听:

//使用自定义函数.
...
cn.removeEventListener(Event.COMPLETE, completeHandler);
...

//使用事件侦听器对象.
...
cn.removeEventListener(Event.COMPLETE, this);
...

AS2.utils.CFDelegate;
AS2.events.Event;
AS2.events.CFEventDispatcher;
这些是什么?下面讲解:

[6.1.创建 CFDelegate 类(修改 Delegate 类)]
CFDelegate 类是 Delegate 类的修改版本.简化了代码(一般不用的功能).提高了执行效率.

此类文档详细:
Classes/AS2/utils/CFDelegate.as

主类:
打开 CFDelegate.as 文档.输入下面的代码:

class AS2.utils.CFDelegate
{
    public static function create(scope:Object, method:Function):Function
    {
        var f:Function = function ()
        {
            method.apply(scope, arguments);
        };
        return f;
    }
}

保存文档.

[6.2.创建 CFEventDispatcher 类(修改 EventDispatcher 类)]
CFEventDispatcher 类是 EventDispatcher 类的修改版本.简化了代码(一般不用的功能).提高了执行效率.

此类文档详细:
Classes/AS2/events/CFEventDispatcher.as

主类:
打开 CFEventDispatcher.as 文档.输入下面的代码:

*/
//----------------------------------------
class AS2.events.CFEventDispatcher
{
    //----------------------------------------
    //构造函数
    public function CFEventDispatcher(){}
    //----------------------------------------
    //当不继承此类时,此属性才有效.
    private static var _ed:CFEventDispatcher;
    //----------------------------------------
    private static function _removeEventListener(queue:Object, handler):Void
    {
        /*
        这里主要用于删除事件数组中的事件处理器.
        */
        if (queue != undefined) {
            var l:Number = queue.length;
            while(l--){
                if(queue[l] == handler){
                    queue.splice(l, 1);
                    return;
                }
            }
        }
    }
    //当不继承此类时.此方法有效.
    public static function initialize(o:Object):Void
    {
        /*
        如果没有继承此类,而是使用 initialize 此方法时, _ed 等于 undefined.然后创建此类的实例.
        最后将事件通知和侦听器管理功能添加到 initialize 方法中的对象 o.
        前面所讲的不继承此类时需添加的三个方法,其实是四个.还有 dispatchQueue 方法.但此方法在
        调用 dispatchEvent 方法时就会自动调用.可能有人会问,为什么没有定义就能调用?因为在函数
        中可以操作对象.从而对对象动态添加方法和属性.这里就是用了在函数中操作对象.
        */
        if (_ed == undefined) {
            _ed = new CFEventDispatcher();
        }
        o.addEventListener = _ed.addEventListener;
        o.removeEventListener = _ed.removeEventListener;
        o.dispatchEvent = _ed.dispatchEvent;
        o.dispatchQueue = _ed.dispatchQueue;
    }
    //----------------------------------------
    private function dispatchQueue(queueObj:Object, eventObj:Object):Void
    {
        /*
         这里主要用于判断事件处理器是对象还是函数.
        */
        if (queueObj[eventObj.type] != undefined) {
            for (var i:String in queueObj[eventObj.type]) {
                var o = queueObj[eventObj.type][i];
                if (typeof (o) == "object" || typeof (o) == "movieclip") {
                    //调用对象中的handleEvent函数.
                    //if (o.handleEvent != undefined) {
                        //o.handleEvent(eventObj);
                    //}
                    //调用对象中的事件同名函数. 
                    //if (o[eventObj.type] != undefined) {
                        o[eventObj.type](eventObj);
                    //}
                } else {
                    //调用自定义函数.
                    o.apply(queueObj, [eventObj]);
                }
            }
        }
    }
    public function dispatchEvent(eventObj:Object):Void
    {
        //将事件源始终指向this(应用此类的对象).
        eventObj.target = this;
        //此句对动态类,或在类中定义"事件名Handler" 这样的函数时才有效.在这里我注释了这句.你如果你想用,可以启用它.
        /*
        用法: 对象.事件名Handler = function(evt:Object){};
        */
        //this[eventObj.type + "Handler"](eventObj);
        this.dispatchQueue(this, eventObj);
    }
    public function addEventListener(event:String, handler):Void
    {
        //这里可以这样理解:
        /*
        使用
        addEventListener("click", 事件处理器);
        添加事件.
        这时, this["click"] 就等于 undefined.
        (this["click"] == undefined) = true
            然后将创建一个新数组来存储事件处理器.
            this["click"] = [];
        然后执行
        CFEventDispatcher._removeEventListener(this["click"], 事件处理器);
        来检测此事件是否有相同的事件处理器.如果是就删除它.
        举个例:当你在一个网站注册用户名时.网站的注册程序会从数据库中检测是否有与你相同的用户名.
        如果有将会提示你重新输入用户名(在这里就是直接删除了).如果没有就会注册成功(这里就在后面
        执行 push).但是网站的注册程序不会从数据库中检测是否有与你相同的密码.
       
        就是说一个事件,可添加多个不同的事件处理器,但不能添加相同的事件处理器.
        当添加新的事件时,也是一样的
       
        最后使用
        this["click"].push(事件处理器);
        将事件处理器添加到事件数组.
        */
        if (this[event] == undefined) {
            this[event] = new Array();
        }
        //ASSetPropFlags 是隐藏的方法.用它和不用它貌似没有区别.大家可以研究下.
        //_global.ASSetPropFlags(this, event, 1);
        CFEventDispatcher._removeEventListener(this[event], handler);
        this[event].push(handler);
    }
    public function removeEventListener(event:String, handler):Void
    {
        //这里我就不啰嗦了.
        CFEventDispatcher._removeEventListener(this[event], handler);
    }
    //----------------------------------------
}

保存文档.

[6.3.创建 Event 类(事件基类,继承 Object 类)]
你可以把它看作事件对象.因应它的工作就是生成事件对象.

此类文档详细:
Classes/AS2/events/Event.as

主类:
打开 Event.as 文档.输入下面的代码:

class AS2.events.Event extends Object
{
    //----------------------------------------
    //事件的常数名.
    public static var COMPLETE:String = "complete";
    public static var CANCEL:String = "cancel";
    public static var CHANGE:String = "change";
    public static var CLOSE:String = "close";
    public static var CONNECT:String = "connect";
    public static var FULLSCREEN:String = "fullScreen";
    public static var OPEN:String = "open";
    public static var REMOVED:String = "removed";
    public static var RESIZE:String = "resize";
    public static var SCROLL:String = "scroll";
    public static var SELECT:String = "select";
    //----------------------------------------
    public var type:String;
    public var target:Object;
    //----------------------------------------
    private var className:String = "Event";
    //----------------------------------------
    //构造函数.
    public function Event(type:String)
    {
        this.type = type;
    }
    //----------------------------------------
    public function toString():String
    {
        var str:String = "";
        for (var i:String in this) {
            if (this[i] != undefined) {
                str += i + "=" + this[i] + " ";
            }
        }
        return "[" + this.className + " " + str.slice(0,str.length - 1) + "]";
    }
    //----------------------------------------
}

保存文档.

此类包含下面内容:
1.事件的常数名.如:

    public static var COMPLETE:String = "complete";
    ...

2.基本的属性.如:

    public var type:String;
    ...

3.className 属性.如:

private var className:String = "Event";
4.构造函数.如:

    public function Event(type:String)
    {
        this.type = type;
    }
5.toString() 方法.如:

    public function toString():String
    {
        var str:String = "";
        for (var i:String in this) {
            if (this[i] != undefined) {
                str += i + "=" + this[i] + " ";
            }
        }
        return "[" + this.className + " " + str.slice(0,str.length - 1) + "]";
    }

如果你嫌此方法阻碍你的执行效率.可以改成如下(标准):

    public function toString():String
    {
        return "[object " + this.className + "]";
    }

这里讲下 toString() 方法.在类中定义此方法.在输出此类实例名实调用此方法.如:

class className
{
    ...
    private var className:String  = "className";
    public function toString():String
    {
        return "[object " + this.className + "]";
    }
    ...
}


import className;
var cn:className = new className();
trace(cn);// 调用 toString() 方法.输出: [object className]

当然你也可以改成 AS3 中 Event 类一样的方法.但没有必要,很少会用到.
如果要向 Event 类传递参数和定义新的事件名,请看下面.

[6.4.创建 IOErrorEvent 类(错误事件类,继承 Event 类)]
此类文档详细:
Classes/AS2/events/IOErrorEvent.as

主类:
打开 IOErrorEvent.as 文档,输入下面的代码:

import AS2.events.Event;
//----------------------------------------
class AS2.events.IOErrorEvent extends Event
{
    //----------------------------------------
    //事件的常数名.
    public static var IO_ERROR:String = "IOError";
    //----------------------------------------
    //属性参数.
    public var text:String;
    //----------------------------------------
    //className 属性
    private var className:String = "IOErrorEvent";
    //----------------------------------------
    //在构造函数中添加参数.
    public function IOErrorEvent(type:String, text:String)
    {
        super(type);
        this.text = text;
    }
    //----------------------------------------
   
}

保存文档.

[6.5.创建 HTTPStatusEvent 类(http状态事件类,继承 Event 类)]
此类文档详细:
Classes/AS2/events/HTTPStatusEvent.as

主类:
打开 HTTPStatusEvent.as 文档.输入下面的代码:

import AS2.events.Event;
//----------------------------------------
class AS2.events.HTTPStatusEvent extends Event
{
    //----------------------------------------
    //事件的常数名.
    public static var HTTP_STATUS:String = "httpStatus";
    //----------------------------------------
    //属性参数.
    public var status:Number;
    //----------------------------------------
    //className 属性
    private var className:String = "HTTPStatusEvent";
    //----------------------------------------
    //在构造函数中添加参数.
    public function HTTPStatusEvent(type:String, status:Number)
    {
        super(type);
        this.status = status;
    }
    //----------------------------------------
   
}

保存文档.

[6.6.示例: EventClass 类(简单的示例)]
此示例文档详细:
Example/AS2/events/Event/EventClass.as
Example/AS2/events/Event/EventExample.as
Example/AS2/events/Event/EventExample.xml
Example/AS2/events/Event/EventExample.fla

主类:
打开 EventClass.as 文档.输入下面的代码:

import AS2.utils.CFDelegate;
import AS2.events.Event;
import AS2.events.IOErrorEvent;
import AS2.events.HTTPStatusEvent;
import AS2.events.CFEventDispatcher;
//----------------------------------------
class EventClass extends CFEventDispatcher
{
    //----------------------------------------
    public var tXML:XML;
    //----------------------------------------
    public function EventClass(url:String)
    {
        this.tXML = new XML();
        this.tXML.onLoad = CFDelegate.create(this, this.XMLonLoad);
        this.tXML.onHTTPStatus = CFDelegate.create(this, this.XMLHTTPStatus);
        this.tXML.load(url);
    }
    public function toString():String
    {
        return "[EventClass]";
    }
    //----------------------------------------
    private function XMLonLoad(success:Boolean):Void
    {
        if (success) {
            this.dispatchEvent(new Event(Event.COMPLETE));
        } else {
            this.dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, "加载错误!请检查 XML 文档地址和网络连接"));
        }
    }
    private function XMLHTTPStatus(httpStatus:Number):Void
    {
        this.dispatchEvent(new HTTPStatusEvent(HTTPStatusEvent.HTTP_STATUS, httpStatus));
    }
    //----------------------------------------
}

保存文档.

示例类:
打开 EventExample.as 文档.输入下面的代码(手指应该很痛吧.呵.我也一样.(可能是无谓的话)):

import EventClass;
import AS2.events.Event;
import AS2.events.IOErrorEvent;
import AS2.events.HTTPStatusEvent;
//----------------------------------------
class EventExample
{
    public function EventExample()
    {
        var ee:EventClass = new EventClass("http://localhost/Examples/AS2/events/Event/EventExample.xml");
        ee.addEventListener(Event.COMPLETE, this.completeHandler);
        ee.addEventListener(IOErrorEvent.IO_ERROR, this.ioErrorHandler);
        ee.addEventListener(HTTPStatusEvent.HTTP_STATUS, this.httpStatusHandler);
    }
    private function completeHandler(evt:Event):Void
    {
        trace(evt);
    }
    private function ioErrorHandler(evt:IOErrorEvent):Void
    {
        trace(evt);
    }
    private function httpStatusHandler(evt:HTTPStatusEvent):Void
    {
        trace(evt);
    }
}

保存文档.
这里注意 XML 文档地址不是本地地址,是用服务器地址的(测试 http 状态用):

var ee:EventClass = new EventClass("http://localhost/Examples/AS2/events/Event/EventExample.xml");
要加载的 XML 文档:
打开 EventExample.xml 文档,随便输入一些内容便可.测试用.

示例 fla 文档:
打开 EventExample.fla 文档.将"图层 1"重命名为  Actions.并在第一帧中输入下面的代码:

new EventExample();
保存文档.
测试 Flash 文档.在 XML 文档成功加载后会在输出面板中显示以下内容:

[HTTPStatusEvent target=[EventClass] status=200 type=httpStatus]
[Event target=[EventClass] type=complete]

当将 XML 地址改成错误时,在输出面板中将显示以下内容:

Error opening URL "http://localhost/Example/AS2/events/Event/EventExamples.xml"
[HTTPStatusEvent target=[EventClass] status=404 type=httpStatus]
[IOErrorEvent target=[EventClass] text=加载错误!请检查 XML 文档地址和网络连接 type=IOError]

下面再看一个示例:
[6.7.示例: Timer 类(定时器,功能跟 AS3 中的 Timer 类一样)]
此示例文档详细:
Classes/AS2/utils/Timer.as
Classes/AS2/utils/TimerEvent.as
Example/AS2/utils/Timer/TimerExample.as
Example/AS2/utils/Timer/TimerExample.fla

主类:
打开 Timer.as 文档,输入下面的代码:

import AS2.utils.TimerEvent;
import AS2.utils.CFDelegate;
import AS2.events.CFEventDispatcher;
//----------------------------------------
class AS2.utils.Timer extends CFEventDispatcher
{
    //----------------------------------------
    private var _timerID:Number;
    private var _delay:Number;
    private var _repeatCount:Number;
    private var _currentCount:Number = 0;
    private var _running:Boolean;
    //----------------------------------------
    /*
    @parameter    delay:            延迟,单位毫秒.
    @parameter    repeatCount:    重复次数.默认为Infinity(正无穷大);
    */
    public function Timer(delay:Number, repeatCount:Number)
    {
        if (isNaN(delay)) {
            return;
        }
        if (isNaN(repeatCount)) {
            repeatCount = Infinity;
        }
        this._delay = delay;
        this._repeatCount = repeatCount;
    }
    //----------------------------------------
    public function reset():Void
    {
        this._currentCount = 0;
        this.stop();
    }
    public function start():Void
    {
        this._timerID = setInterval(CFDelegate.create(this, this.startTimer), this._delay);
        this._running = true;
    }
    public function stop():Void
    {
        clearInterval(this._timerID);
        this._running = false;
    }
    public function toString():String
    {
        return "[Timer]";
    }
    //----------------------------------------
    private function startTimer():Void
    {
        this._currentCount++;
        this.dispatchEvent(new TimerEvent(TimerEvent.TIMER, this._currentCount));
        if (this._currentCount == this._repeatCount) {
            this.reset();
            this.dispatchEvent(new TimerEvent(TimerEvent.TIMER_COMPLETE));
        }
    }
    //----------------------------------------
    public function get delay():Number
    {
        return this._delay;
    }
    public function set delay(d:Number):Void
    {
        this._delay = d;
    }
    public function get repeatCount():Number
    {
        return this._repeatCount;
    }
    public function set repeatCount(r:Number):Void
    {
        this._repeatCount = r;
    }
    public function get currentCount():Number
    {
        return this._currentCount;
    }
    public function get running():Boolean
    {
        return this._running;
    }
    //----------------------------------------
}

保存文档.

Timer 事件类:
打开 TimerEvent.as 文档,输入下面的代码:

import AS2.events.Event;
//----------------------------------------
class AS2.utils.TimerEvent extends Event
{
    //----------------------------------------
    public static var TIMER:String = "timer";
    public static var TIMER_COMPLETE:String = "timerComplete";
    //----------------------------------------
    public var currentCount:Number;
    //----------------------------------------
    private var className:String = "TimerEvent";
    //----------------------------------------
    public function TimerEvent(type:String, currentCount:Number)
    {
        super(type);
        this.currentCount = currentCount;
    }
    //----------------------------------------
}

保存文档.

示例类:
打开 TimerExample.as 文档,输入下面的代码:

import AS2.utils.Timer;
import AS2.utils.TimerEvent;
//----------------------------------------
class TimerExample
{
    //----------------------------------------
    public function TimerExample()
    {
        var te:Timer = new Timer(1000, 5);
        te.addEventListener(TimerEvent.TIMER, this.timerHandler);
        te.addEventListener(TimerEvent.TIMER_COMPLETE, this.timerCompleteHandler);
        te.start();
    }
    private function timerHandler(evt:TimerEvent):Void
    {
        trace("timer: " + evt);
    }
    private function timerCompleteHandler(evt:TimerEvent):Void
    {
        trace("timerComplete: " + evt);
    }
    //----------------------------------------
}

保存文档.

示例 fla 文档:
打开 TimerExample.fla 文档,将"图层 1"重命名为  Actions.并在第一帧中输入下面的代码:

new TimerExample();
保存文档.
测试 Flash 文档.在输出面板可以看到下面的内容:

timer: [TimerEvent target=[Timer] currentCount=1 type=timer]
timer: [TimerEvent target=[Timer] currentCount=2 type=timer]
timer: [TimerEvent target=[Timer] currentCount=3 type=timer]
timer: [TimerEvent target=[Timer] currentCount=4 type=timer]
timer: [TimerEvent target=[Timer] currentCount=5 type=timer]
timerComplete: [TimerEvent target=[Timer] type=timerComplete]

经典论坛讨论:
http://bbs.blueidea.com/thread-2768209-1-1.html

出处:蓝色理想
责任编辑:蓝色月光

上一页 [AS2]事件处理机制 -- 使用addListener方法 二 下一页 [AS2]事件处理机制 -- 小结

◎进入论坛Flash专栏版块参加讨论

作者文章
Flash处理外部XML文档数据
Flash处理XML文档数据教程
关键字搜索 常规搜索 推荐文档
热门搜索:CSS Fireworks 设计比赛 网页制作 web标准 用户体验 UE photoshop Dreamweaver Studio8 Flash 手绘 CG
站点最新 站点最新列表
周大福“敬•自然”设计大赛开启
国际体验设计大会7月将在京举行
中国国防科技信息中心标志征集
云计算如何让安全问题可控
云计算是多数企业唯一拥抱互联网的机会
阿里行云
云手机年终巨献,送礼标配299起
阿里巴巴CTO王坚的"云和互联网观"
1499元买真八核 云OS双蛋大促
首届COCO桌面手机主题设计大赛
栏目最新 栏目最新列表
浅谈JavaScript编程语言的编码规范
如何在illustrator中绘制台历
Ps简单绘制一个可爱的铅笔图标
数据同步算法研究
用ps作简单的作品展示页面
CSS定位机制之一:普通流
25个最佳最闪亮的Eclipse开发项目
Illustrator中制作针线缝制文字效果
Photoshop制作印刷凹凸字体
VS2010中创建自定义SQL Rule
>> 分页 首页 前页 后页 尾页 页次:7/81个记录/页 转到 页 共8个记录

蓝色理想版权申明:除部分特别声明不要转载,或者授权我站独家播发的文章外,大家可以自由转载我站点的原创文章,但原作者和来自我站的链接必须保留(非我站原创的,按照原来自一节,自行链接)。文章版权归我站和作者共有。

转载要求:转载之图片、文件,链接请不要盗链到本站,且不准打上各自站点的水印,亦不能抹去我站点水印。

特别注意:本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有,文章若有侵犯作者版权,请与我们联系,我们将立即删除修改。

您的评论
用户名:  口令:
说明:输入正确的用户名和密码才能参与评论。如果您不是本站会员,你可以注册 为本站会员。
注意:文章中的链接、内容等需要修改的错误,请用报告错误,以利文档及时修改。
不评分 1 2 3 4 5
注意:请不要在评论中含与内容无关的广告链接,违者封ID
请您注意:
·不良评论请用报告管理员,以利管理员及时删除。
·尊重网上道德,遵守中华人民共和国的各项有关法律法规
·承担一切因您的行为而直接或间接导致的民事或刑事法律责任
·本站评论管理人员有权保留或删除其管辖评论中的任意内容
·您在本站发表的作品,本站有权在网站内转载或引用
·参与本评论即表明您已经阅读并接受上述条款
推荐文档 | 打印文档 | 评论文档 | 报告错误  
专业书推荐 更多内容
网站可用性测试及优化指南
《写给大家看的色彩书1》
《跟我去香港》
众妙之门—网站UI 设计之道
《Flex 4.0 RIA开发宝典》
《赢在设计》
犀利开发—jQuery内核详解与实践
作品集 更多内容

杂⑦杂⑧ Gold NORMANA V2