在平常的应用中自定义事件和自定义组件是非常重要的,下面分别介绍它们的应用。
自定义事件分为两种情况:
1继续自Event事件
2直接用Event事件的临时常量
自定义组件也分为两种:
1mxml形式
2 as形式
这两种形式都可以继续自现有有组件,也可以不继续原有组件,完全重新定义。
这里先说自定义组件,在自定义组件的创建过程中,会涉及到自定义事件。所以,我们用两种不同的自定义事件方式来实现自定义组件。
自定义事件时,事件对象的构造函数中的参数bubbles的值,一般为false,这样事件就不会流经冒泡阶段,Event的bubbles为false,MouseEvent的bubbles值为true;
如果想监听这个事件的对象已经添加到了显示列表中,那么它添加监听时 addEventListener的参数useCapture默认是false----监听目标阶段和冒泡阶段,并且事件对象的bubbles值也为false----事件不流经冒泡阶段,那么这个事件只会被它的目标阶段监听到。
如果事件目标不在显示列表中,则 Flash Player 或 AIR 将事件对象直接调度到事件目标。例如,Flash Player 将progress 事件对象直接调度到 URLStream 对象。但是,如果事件目标在显示列表中,则 Flash Player 将事件对象调度到显示列表,事件对象将在显示列表中穿行,直到到达事件目标。
目标:指的是发送事件的对象。发送者就是目标,目标就是发送者。
当前目标:是指事件在事件流中现处流经的位置。
一下面是自定义事件为继承自Event的源码:
有两个自定义组件分别是AS形式―Custom和MXML形式-MyButton
在看自定义组件之前先看一下Event标签的作用:
Event元数据标签用来声明那些被自定义类分派的事件。将这个元数据标签添加到类定义中之后,你就可以在MXML标签中添加事件处理函数来初始化该自定义类。
Custom ButtonLabel class using[Event]
package comps
{
importmx.controls.Button;
importflash.events.Event;
// Define thecustom event
[Event(name="labelChanged",type="flash.events.Event")]
publicclassButtonLabel extends Button
{
// property tohold labelvalue
privatevar_myLabel:String;
// public settermethod
public functionsetmyLabel(s:String):void
{
_myLabel =s;
this.label =s;
// Createanddispatch custom event
vareventObj:Event = new Event("labelChanged");
dispatchEvent(eventObj);
}
}
}
Using the ButtonLabel class withthe labelChanged [Event]
<fx:Script>
<![CDATA[
importmx.controls.Alert;
importflash.events.Event;
// method tohandle customevent
publicfunctionlabelChanged(eventObj:Event):void
{
myTA.text=myTA.text + "\n"+ eventObj.target.label;
myTA.verticalScrollPosition= myTA.verticalScrollPosition +20;
}
]]>
</fx:Script>
<mx:Paneltitle="Event Sample"width="500" height="275"
paddingTop="10"paddingLeft="10"paddingRight="10" paddingBottom="10"layout="absolute">
<mx:TextInputid="buttonLabelTI"
change="myButton.myLabel=buttonLabelTI.text"x="10"y="9"/>
<!--Instantiatecustom class and define method to handle label-Changedevent-->
<comps:ButtonLabelid="myButton"labelChanged="labelChanged(event);"x="10"y="39"/>
<mx:TextAreaid="myTA" width="200"height="200" x="249"y="10"/>
</mx:Panel>
下面是源码:
MyEvent事件:
package event
{
importflash.events.Event;
public classMyEvent extends Event
{
public static constEVENT_TEST:String="EventTest";
public functionMyEvent(type:String, bubbles:Boolean=false,cancelable:Boolean=false)
{
super(type,bubbles, cancelable);
}
}
}
MyButton组件:
<?xmlversion="1.0" encoding="utf-8"?>
<s:Button xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo"
click="dispatchEvent(newMyEvent(MyEvent.EVENT_TEST));">
<fx:Script>
<![CDATA[
importevent.MyEvent;
]]>
</fx:Script>
<fx:Metadata>
<!--在Metadata标签下定义Event编译期间检查,为这个自定义组件注册事件-->
[Event(name ="EventTest",type ="event.MyEvent")]
</fx:Metadata>
</s:Button>
CustomEvent事件:
package
{
importflash.events.Event;
public classCustomEvent extends Event
{
public static constEVENT_NAME:String= "event_name";
public vardata:Object;
public functionCustomEvent(type:String, bubbles:Boolean=false,cancelable:Boolean=false, data:Object=null) //如果想在冒泡阶段捕获这个事件,bubbles值应该为true
{
super(type, bubbles, cancelable);
this.data=data;
}
override public functionclone():Event
{
return newCustomEvent(type, bubbles, cancelable, data);
}
}
}
Custom组件:
package
{
importflash.events.EventDispatcher;
importmx.containers.Canvas;
importmx.core.UIComponent;
[Event(name="changeTest",type="flash.events.Event")]
public class Customextends Canvas
{
public varName:String = null;
public functionCustom()
{
}
public functionprintEvent(e:CustomEvent):void
{
trace(Name+"收到");
}
}
}
主程序:
<?xmlversion="1.0" encoding="utf-8"?>
<s:WindowedApplicationxmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:my="button.*"
xmlns:event="event.*"
>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<fx:Script>
<![CDATA[
importevent.MyEvent;
importmx.core.UIComponent;
//实验1 将自定义组件添加到显示列表中
public varcustom1:Custom = new Custom();
public varcustom2:Custom = new Custom();
public var ce:CustomEvent= new CustomEvent(CustomEvent.EVENT_NAME);
protected functionstartTimer(event:MouseEvent):void
{
custom1.Name = "com1";
custom2.Name= "com2";
this.addElement(custom1);
this.addElement(custom2);
this.addEventListener(CustomEvent.EVENT_NAME,handleEventAS,true);
this.parent.addEventListener(CustomEvent.EVENT_NAME,handleEventAS,true);
custom1.addEventListener(CustomEvent.EVENT_NAME,custom1.printEvent,false);
custom2.addEventListener(CustomEvent.EVENT_NAME,custom2.printEvent,false);
// custom1.addEventListener("changeTest",handleEventAS);
custom1.dispatchEvent(ce);
// this.dispatchEvent(newEvent("changeTest"));
}
public functionhandleEventAS(e:CustomEvent):void
{
trace(e.currentTarget);
}
public functionhandleEvent(e:MyEvent):void
{
trace(e.target);
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<s:HGroup id="groupTimer">
<s:Button id="start"label="开始"click="startTimer(event)"/>
<s:TextInputtext="" id="txt"/>
</s:HGroup>
<s:Group id="group2">
<my:MyButton id="my1"EventTest="handleEvent(event)" x="208" y="213"></my:MyButton>
<my:MyButton id="my2"EventTest="handleEvent(event)" x="209" y="258"></my:MyButton>
</s:Group>
</s:WindowedApplication>
二发送事件还有另一种方式
custom1.dispatchEvent(new Event("changeTest",false));
直接发送Event对象,可以用第二个参数bubbles的值来控制是否流经冒泡阶段,Event默认是false不流经。它的用法与继承Event的事件用法一样。需要注意的地方就是:如果目标不在显示列表中,事件将会被直接发送给目标,也就是自己。
如果目标在显示列表中,那么事件会在事件流中流动。
protected functionstartTimer(event:MouseEvent):void
{
custom1.Name = "com1";
this.addElement(custom1);
custom1.addEventListener("changeTest",ChangeTest);
this.addEventListener("changeTest",ChangeTest,true);
this.addEventListener("changeTest",ChangeTest);
custom1.dispatchEvent(new Event("changeTest",false));
custom1.dispatchEvent(new Event("changeTest",true));
}
public function ChangeTest(e:Event):void
{
trace(e.eventPhase);
}