Flash/Flex学习笔记(34):AS3中的自定义事件

类似C#中自定义事件需要一个自定义的EventArgs子类一样,AS3也需要开发者自定义一个Event类的子类,这里我们假设一种场景:设计一个Person(人物)类,里面有Age(年龄),Name(姓名),我们希望每当Person类的实例Age(年纪)发生变化时,能触发一些自定义事件,从而调用某些特定的处理方法。

1.先设计Event类的子类AgeChangeEvent

package {

	import flash.events.Event;

	public class AgeChangeEvent extends Event {

		public static const AGE_OUT_OF_RANGE:String="AGE_OUT_OF_RANGE";
		public static const AGE_CHANGE:String="AGE_CHANGE";

		public function AgeChangeEvent(eventType:String){
			super(eventType);
		}
	}
}

这里我们定义了二类事件:年龄变化(AGE_CHANGE)、年龄超出范围(AGE_OUT_OF_RANGE)

2.再来设计Person类

package {

	import flash.display.Sprite;

	public class Person extends Sprite {

		private var _age:uint;

		private var _personName:String;

		public function Person(personName:String,age:uint) {
			this._age=age;
			this._personName=personName;
		}

		//将_age封装成属性
		public function get Age():uint{
			return _age;
		}

		//Age属性的setter方法(在这里加入事件派发处理)
		public function set Age(age:uint):void{

			if (age!=this._age){
				var _ageChangeEvent1:AgeChangeEvent = new AgeChangeEvent(AgeChangeEvent.AGE_CHANGE);
				dispatchEvent(_ageChangeEvent1);//触发Age改变事件
			}

			if (age>=120){
				var _ageChangeEvent2:AgeChangeEvent = new AgeChangeEvent(AgeChangeEvent.AGE_OUT_OF_RANGE);
				dispatchEvent(_ageChangeEvent2);//触发Age超过正常范围事件
			}

			this._age = age;

		}		

		//覆盖父类的toString方法
		public override function toString():String{
			return "“" + this._personName + "”童鞋一晃今年都已经“" + this._age + "”岁了,真是岁月不饶人啊.";
		}

	}
}

注意这里的dispatchEvent处理部分,先定义一个事件(参数)对象,然后派发事件.(类似C#中的委托/事件机制,Person类并不知道最终Peson的使用者将如何处理这二个事件,但只要遵守约定就能正确调用开发者执行的处理方法)

3.测试刚才的事件,新建一个Flash File(ActionScript3.0)的fla文件,在第一帧写入以下测试代码 :

var jimmy:Person = new Person("菩提树下的杨过",30);
trace(jimmy.toString());

jimmy.Age = 31;//现在还没注册任何事件,所以啥也不会触发

//注册事件
jimmy.addEventListener(AgeChangeEvent.AGE_CHANGE,AgeChangeHandler);

function AgeChangeHandler(e:AgeChangeEvent):void{
	trace("注意:这家伙年龄改了!");
}

jimmy.Age = 32; //现在改变年龄时,将触发AgeChangeHandler事件

jimmy.Age = 150; //将再次触发AgeChangeHandler事件

//再注册一个事件
jimmy.addEventListener(AgeChangeEvent.AGE_OUT_OF_RANGE,AgeOutOfRangeHandler);

function AgeOutOfRangeHandler(e:AgeChangeEvent):void{
	trace("注意:这老家伙居然说自己年龄超过120岁了!");
}

jimmy.Age = 149;//将同时触发AGE_CHANGE与AGE_OUT_OF_RANGE事件

建议大家先猜猜结果,动手实践一下,再看下面的输出结果:

“菩提树下的杨过”童鞋一晃今年都已经“30”岁了,真是岁月不饶人啊.
注意:这家伙年龄改了!
注意:这家伙年龄改了!
注意:这家伙年龄改了!
注意:这老家伙居然说自己年龄超过120岁了!

有时候,我们还希望AgeChangeEvent参数还能附带一些额外信息,这个也难不倒AS,把AgeChangeEvent改造一下(注意新增部分):

package {

	import flash.events.Event;

	public class AgeChangeEvent extends Event {

		public static const AGE_OUT_OF_RANGE:String="AGE_OUT_OF_RANGE";
		public static const AGE_CHANGE:String="AGE_CHANGE";

		//新增部分
		private var _OldAge:uint,_NewAge:uint;

		public function AgeChangeEvent(eventType:String,oldAge:uint,newAge:uint){
			this._OldAge = oldAge;
			this._NewAge = newAge;
			super(eventType);
		}

		public function get OldAge():uint{
			return _OldAge;
		}

		public function get NewAge():uint{
			return _NewAge;
		}
	}
}

Person类里Age的setter部分也要改一下:

//Age属性的setter方法(在这里加入事件派发处理)
		public function set Age(age:uint):void{

			if (age!=this._age){
				var _ageChangeEvent1:AgeChangeEvent = new AgeChangeEvent(AgeChangeEvent.AGE_CHANGE,this._age,age);
				dispatchEvent(_ageChangeEvent1);//触发Age改变事件
			}

			if (age>=120){
				var _ageChangeEvent2:AgeChangeEvent = new AgeChangeEvent(AgeChangeEvent.AGE_OUT_OF_RANGE,this._age,age);
				dispatchEvent(_ageChangeEvent2);//触发Age超过正常范围事件
			}

			this._age = age;

		}

测试fla中的代码稍加改动:

var jimmy:Person = new Person("菩提树下的杨过",30);
trace(jimmy.toString());

jimmy.Age = 31;//现在还没注册任何事件,所以啥也不会触发

//注册事件
jimmy.addEventListener(AgeChangeEvent.AGE_CHANGE,AgeChangeHandler);

function AgeChangeHandler(e:AgeChangeEvent):void{
	trace("注意:这家伙年龄从" + e.OldAge +"改成" + e.NewAge + "了!");
}

jimmy.Age = 32; //现在改变年龄时,将触发AgeChangeHandler事件

jimmy.Age = 150; //将再次触发AgeChangeHandler事件

//再注册一个事件
jimmy.addEventListener(AgeChangeEvent.AGE_OUT_OF_RANGE,AgeOutOfRangeHandler);

function AgeOutOfRangeHandler(e:AgeChangeEvent):void{
	trace("注意:这老家伙居然说自己年龄超过120岁,现在已经有" + e.NewAge + "了!");
}

jimmy.Age = 149;//将同时触发AGE_CHANGE与AGE_OUT_OF_RANGE事件

新的输出结果:

“菩提树下的杨过”童鞋一晃今年都已经“30”岁了,真是岁月不饶人啊.
注意:这家伙年龄从31改成32了!
注意:这家伙年龄从32改成150了!
注意:这家伙年龄从150改成149了!
注意:这老家伙居然说自己年龄超过120岁,现在已经有149了!

后记:自定义事件可以广泛应用于很多场景,比如我们可以自己做一个控制滑块MovieClip,里面定义一个ValueChange事件,其它需要的地方(比如音量大小控制,对象Alpha值控制,对象大小控制...),只要定义自己的处理函数,然后注册到该事件即可

源代码:http://files.cnblogs.com/yjmyzz/as3_custom_events.rar

 

最后做为对比和复习,贴出C#版的自定义事件:

AgeChangeEventArgs类

using System;

namespace EventDemo
{
    public class AgeChangeEventArgs:EventArgs
    {
        private uint _oldAge;
        private uint _newAge;

        public AgeChangeEventArgs(uint oldAge, uint newAge)
        {
            this._oldAge = oldAge;
            this._newAge = newAge;
        }

        public uint OldAge { get { return _oldAge; } }

        public uint NewAge { get { return _newAge; } }
    }
}

Person类

namespace EventDemo
{
    public class Person
    {
        public delegate void AgeChangeEventHandler(object sender, AgeChangeEventArgs e);

        public event AgeChangeEventHandler AgeChangeEvent;
        public event AgeChangeEventHandler AgeOutOfRangeEvent;

        private uint _age;
        private string _name;

        public uint Age
        {
            get { return Age; }
            set
            {
                if (value != _age)
                {
                    if (AgeChangeEvent != null)
                    {
                        AgeChangeEvent(this, new AgeChangeEventArgs(_age, value));
                    }
                }

                if (value >= 120)
                {
                    if (AgeOutOfRangeEvent != null)
                    {
                        AgeOutOfRangeEvent(this, new AgeChangeEventArgs(_age, value));
                    }
                }

                _age = value;
            }
        }

        public string Name
        {
            get { return _name; }
            set
            {

                _name = value;
            }
        }

        public Person(string pName, uint pAge)
        {
            this._age = pAge;
            this._name = pName;
        }

        public override string ToString()
        {
            return "“" + this._name + "”今年已经“" + this._age + "”岁了!";
        }
    }
}

测试程序:

using System;

namespace EventDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person("菩提树下的杨过", 30);

            Console.WriteLine(p.ToString());

            p.Age = 31;

            p.AgeChangeEvent += new Person.AgeChangeEventHandler(p_AgeChangeEvent);

            p.Age = 32;

            p.AgeOutOfRangeEvent += new Person.AgeChangeEventHandler(p_AgeOutOfRangeEvent);

            p.Age = 150;

            Console.ReadKey();
        }

        static void p_AgeOutOfRangeEvent(object sender, AgeChangeEventArgs e)
        {
            Console.WriteLine("天啊,这家伙的年龄居然已经达到" + e.NewAge + "岁了!");
        }

        static void p_AgeChangeEvent(object sender, AgeChangeEventArgs e)
        {
            Console.WriteLine("注意:这家伙的年龄从" + e.OldAge + "岁改成了" + e.NewAge + "岁!");
        }
    }
}
时间: 2024-07-30 20:03:51

Flash/Flex学习笔记(34):AS3中的自定义事件的相关文章

Flash/Flex学习笔记(16):如何做自定义Loading加载其它swf

const FILE_PATH:String="main.swf"; const CLASS_NAME:String="MainSwf"; var loader:Loader; var request:URLRequest; loader = new Loader(); request=new URLRequest(FILE_PATH); loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onCompl

Flash/Flex学习笔记(37):不用系统组件(纯AS3)的视频播放器--只有8.82K

以前为了赶项目,利用系统组件制作过一款视频播放器(见Flash/Flex学习笔记(6):制作基于xml数据源的flv视频播放器),但是系统组件实在是太大了,最终生成的swf居然有103K,随着AS3的深入学习,昨天又弄了一个只用AS3的播放器,最终只有8.82K,呵呵,这肥减得那是相当厉害. 用到了上一篇(Flash/Flex学习笔记(35):自己动手实现一个滑块控件(JimmySilder))里自己写的的滑块控件,主要代码如下(关键是NetConnection与NetStream对象的使用):

Flash/Flex学习笔记(57):实用技巧

布朗运动: varnumDots:uint=50; varfriction:Number=0.9; vardots:Array; varlife:uint=0; functioninit(){ graphics.lineStyle(0,0xffffff,.5); dots=newArray(); for(vari:uint=0;i<numDots;i++){ vardot:Ball=newBall(2,0x00ff00); dot.x=Math.random()*stage.stageWidth

Flash/Flex学习笔记(6):制作基于xml数据源的flv视频播放器

今天折腾了大半天,总算搞出了一个功能简单的视频播放器,可以向公司领导交差了 :) 步骤: 1.Flash CS4 中 先拖一个"FLVPlayback"组件到舞台上 注:FLVPlayback本身已经具备了flv播放的基本功能,简单设置下属性就能播放视频了 2.加载xml数据源 xml数据源格式如下: <?xml version="1.0" encoding="utf-8"?> <data> <item flv=&q

Flash/Flex学习笔记(51):3维旋转与透视变换(PerspectiveProjection)

Flash/Flex学习笔记(49):3D基础 里已经介绍了3D透视的基本原理,不过如果每次都要利用象该文中那样写一堆代码,估计很多人不喜欢,事实上AS3的DisplayObject类已经内置了z坐标.rotationX.rotationY.rotationZ属性,再加上PerspectiveProjection类用于处理透视转换,基本上可以满足大多数的3D要求. import flash.events.Event; import flash.display.Sprite; import fla

Flash/Flex学习笔记(5):捕获摄像头(续)--在线抓屏并保存到客户端本地

必须有摄像头上面的演示才能正常播放. 思路 使用摄像头以及在线抓屏在上一节Flash/Flex学习笔记(2)捕获摄像头 里已经讲过了就不重复粘贴了至于在客户端保存文件Flash里用起来也很简单:直接调用 FileReference 即可另外为了减少图片大小还可能借助AS3.0的扩展库项目地址http://code.google.com/p/as3corelib/把bmp格式的位置转换成jpeg再保存   扩展 结合本文的方法再配合Flash/Flex学习笔记(4)如何打开网页及Get/Post数

Flash/Flex学习笔记(24):粒子效果

粒子爆炸: 仍然要用到以前的小球类,不过稍加改造 package { import flash.display.Sprite; //小球 类 public class Ball extends Sprite { public var radius:uint;//半径 public var color:uint;//颜色 public var vx:Number=0;//x轴速度 public var vy:Number=0;//y轴速度 public function Ball(r:Number

Flash/Flex学习笔记(25):摩擦力与屏幕环绕

摩擦力: 假如一个物体在某个方向上沿直线运行,摩擦力会使该方向上的速度越来越小,直到停止. 上图示意了该过程,物体以moveAngle角度正向运动,最终的速度speed矢量为vx矢量与vy矢量的矢量和,在每个单位时间内的位移即Speed矢量的大小,分解到x,y轴后,即为vx与vy:加入摩擦力后,speed矢量每单位时间将减少Friction值,也就是视觉上的越来越慢. var ball:Ball = new Ball(10); ball.x = stage.stageWidth/2; ball.

Flash/Flex学习笔记(46):正向运动学

所谓"正向运动学"通俗点讲就是把几个连接部件的一端固定起来,另一个端可以自由(向前/向外)运动.比如人的行走,单个下肢可以理解为脚连接小腿,小腿连接大腿,大腿连接腰.行走的过程,相当于二条腿相对固定于腰部,大腿运动驱动小腿,小腿又驱动脚,从而带动整个连接系统的一系列运动. 先来一个基本的关节类Segment:(就是一个圆角矩形+二个小圆圈) package { import flash.display.Sprite; import flash.geom.Point; public cl