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值控制,对象大小控制...),只要定义自己的处理函数,然后注册到该事件即可
源代码:https://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 + "岁!"); } } }
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。