类似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 + "岁!");
}
}
}