Flex中的事件機制
2006-11-28 10:37
一. 事件簡介
事件可以由外設觸發, 比如:鍵盤,鼠標, 也可能是外部輸入, 比如:web service的返回. 事件還能由組件的外觀和生命周期發生變化時觸發, 比如:組件的創建或者改變大小. 所有用戶與應用交互都會產生事件.用戶沒有直接與應用交互也可能產生事件, 比如:數據裝載完畢. 你可以在程序中使用事件監聽器監聽這些事件. 事件監聽器是函數方法用于響應指定的事件. 有時也稱之為事件處理器. Flex的事件模型基于DOM3事件模型. 組件產生派發事件并消費(監聽)其他事件.如果一個對象想要了解其他對象事件的信息, 可以注冊一個監聽器. 當事件發生時,對象派發此事件到所有注冊過的監聽器中. 組件有Flex提供的內建事件. 也可以使用派發-監聽模型定義自己的事件監聽器, 并指定監聽器監聽何種事件. 二. 事件流簡介 當一個事件被派發出來時, 事件對象從根節點開始自上而下開始掃描display list, 一直到目標對象, 檢查每個節點是否有相應的監聽器. 目標對象指的是display list中產生事件的對象. 比如: <mx:Panel> <mx:HBox> <mx:VBox> <mx:Button /> </mx:VBox> </mx:HBox> </mx:Panel> 如何此時 resize了VBox, 則會從根(Application)開始, 下來檢查Panel, HBox, 直到目標對象-產生resize事件的VBox為止. 三. 事件的派發 Flex中可以通過dispatchEvent()方法手工派發事件, 所有UIComponent的子類都可以調用此方法. 語法: objectInstance.dispatchEvent(new Event("event_type"):Boolean 參數event_type是Event對象的type屬性. 函數的返回值總是True. 可以使用此方法派發任意事件, 而不僅僅是用戶自定義事件, 比如: 可以派發一個Button的Click事件. var result:Boolean = buttonInstance.dispatchEvent(new Event(MouseEvent.CLICK)); 在Flex應用中不是必須對新派發的事件進行處理, 如果觸發了一個事件, 而沒有對應的Listener時,Flex忽略此事件. 如果想給Event對象添加新屬性, 就必須繼承Event類,然后定義新屬性 四.事件的傳播: 事件觸發后, Flex有3個檢測事件監聽器的階段, 3個階段的發生的順序如下: 1. 捕獲 2. 目標 3. 上浮 在任意一個階段, 節點們都有機會操作事件. 比如: 用戶點擊了一個在VBox中的Button, 在捕獲階段, Flex檢查Application對象(根節點)和VBox是否有監聽器處理此事件. Flex然后在目標階段觸發按鈕的監聽器. 在上浮階段, VBox和應用以與捕獲階段相反的順序再次獲得機會處理事件. 在Actionscript3.0中,你可以在任意目標節點上注冊事件監聽器. 但是部分事件會被直接傳給目標節點,比如Socket類. 捕獲階段的節點順序是從父節點到子節點的, 而上浮階段剛好相反. 捕獲事件缺省是關閉的,也就是說如果要捕獲事件, 必須顯式指定在捕獲階段進行處理. 每一個Event都有target和currentTarget屬性, 幫助跟蹤事件傳播的過程. 捕獲階段: 在捕獲階段,Flex在顯示列表中檢查事件的祖先是否注冊了事件的監聽器. Flex從根節點開始順序而下. 大多數情況中, 根節點是Application對象. 同時, Flex改變事件的currentTarget值. 缺省情況下, 在此階段,沒有容器監聽事件. use_capture參數的值是False,在此階段添加監聽的唯一方法是在調用add_listener時, 傳入一個為True值的use_capture參數, 比如: myAccordion.addEventListener(MouseEvent.MOUSE_DOWN, customLogEvent, true); 如果是在Mxml中添加監聽, Flex設置此參數為False, 沒有辦法進行修改. 如果設置了use_capture為True, 那么事件將不會上浮. 如果既想捕獲又想上浮就必須調用 addEventListener兩次. 一次use_capture參數為true, 一次為false; 捕獲很少使用, 上浮的使用更為普遍. 目標階段: 在目標階段, Flex激發事件的監聽程序, 不檢查其他的節點. 上浮階段: 事件只在bubbles屬性為True時才進行上浮. 可以上浮的事件包括: change, click, doubleClick, keyDown, keyUp, mouseDown, mouseUp. 在上浮階段, Flex改變事件的currentTarget屬性, 而target屬性是初始派發事件的對象. 查詢事件階段: 使用事件的eventPhase可以獲得事件當前的階段, 1: CAPTURE_PHASE 2: AT_TARGET 3: BUBBLING_PHASE 示例: private function determineState(event:MouseEvent):Void { Debug.trace(event.eventPhase + ":" + event.currentTarget.id); } 停止傳播: 使用下面兩個函數停止事件的傳播: stopPropagation() stopImmediatePropagation() |
? ?? ? 在Flex中定義事件有兩中情況,分別是ActionScript和MXML中定義。
? ?? ? 在ActionScript中定義:
CODE:
[Event(name="myEnableEvent", type="flash.events.Event")]
public class MyComponent extends UIComponent
{
? ?? ?? ???...
}
在MXML中定義:public class MyComponent extends UIComponent
{
? ?? ?? ???...
}
CODE:
<mx:Metadata>
? ? [Event(name="DataChange", type="DataChangeEvent")]
</mx:Metadata>
DataChangeEvent事件參數的定義:? ? [Event(name="DataChange", type="DataChangeEvent")]
</mx:Metadata>
CODE:
import flash.events.Event;
public class DataChangeEvent extends flash.events.Event
{
? ?? ? public function DataChangeEvent()
? ?? ? {
? ?? ?? ?? ???super("DataChange");
? ?? ? }
? ?? ? public var Data:Object;
}
在自定義控件中定義和觸發事件:public class DataChangeEvent extends flash.events.Event
{
? ?? ? public function DataChangeEvent()
? ?? ? {
? ?? ?? ?? ???super("DataChange");
? ?? ? }
? ?? ? public var Data:Object;
}
CODE:
<?xml version="1.0" encoding="utf-8"?>
<mx:Form xmlns:mx="http://www.adobe.com/2006/mxml" width="212" height="56">
<mx:Metadata>
? ?? ???[Event(name="DataChange", type="DataChangeEvent")]
? ? </mx:Metadata>
<mx:Button label="Button" click="Change()"/>
? ?? ? <mx:Script>
? ?? ?? ?? ???<![CDATA[
? ?? ?? ?? ?? ?? ?? ?function Change():void
? ?? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?? ?? ? this.dispatchEvent(new DataChangeEvent());
? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ???]]>
? ?? ? </mx:Script>
</mx:Form>
容器接收相關自定義控件事件:<mx:Form xmlns:mx="http://www.adobe.com/2006/mxml" width="212" height="56">
<mx:Metadata>
? ?? ???[Event(name="DataChange", type="DataChangeEvent")]
? ? </mx:Metadata>
<mx:Button label="Button" click="Change()"/>
? ?? ? <mx:Script>
? ?? ?? ?? ???<![CDATA[
? ?? ?? ?? ?? ?? ?? ?function Change():void
? ?? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?? ?? ? this.dispatchEvent(new DataChangeEvent());
? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ???]]>
? ?? ? </mx:Script>
</mx:Form>
CODE:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:ns1="*">
? ?? ?
? ?? ? <ns1:EmployeeCombo x="146" y="132" DataChange="onChange(event)" >
? ?? ? </ns1:EmployeeCombo>
? ?? ? <mx:Script>
? ?? ?? ?? ???<![CDATA[
? ?? ?? ?? ?? ?? ?? ?import mx.controls.Alert;
? ?? ?? ?? ?? ?? ?? ?function onChange(e:DataChangeEvent)
? ?? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?? ?? ?
? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ???]]>
? ?? ? </mx:Script>
</mx:Application>
其實自定義事件的現實也很簡單,但起著非常重要的作用;正是因為有了事件的機制,使得大部分重復的功能抽取到自定義控件中,從而達到一個很高的代碼重用性。
? ?? ?
? ?? ? <ns1:EmployeeCombo x="146" y="132" DataChange="onChange(event)" >
? ?? ? </ns1:EmployeeCombo>
? ?? ? <mx:Script>
? ?? ?? ?? ???<![CDATA[
? ?? ?? ?? ?? ?? ?? ?import mx.controls.Alert;
? ?? ?? ?? ?? ?? ?? ?function onChange(e:DataChangeEvent)
? ?? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?? ?? ?
? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ???]]>
? ?? ? </mx:Script>
</mx:Application>