1.在FlashPlayer創建完一個組件時,它會分派一個creationComplete事件。DisplayObject 類是 EventDispatcher 類的子類,這意味者每一個 DisplayObject 都可以註冊事件監聽器,並在事件發生的時候進行相應的處理。
2.用戶自定義的類可以業務邏輯中分派事件。
3.EnterFrame事件由AVM觸發,並以程序中幀的刷新速率進行觸發。
addEventListener(Event.ENTERFRAME, onEnteringFrame);
4.可以分派自定義事件。
JAVA中的事件監聽者是對象,AS3中事件監聽者只是Function。如果要在自定義的AS3類裏分派事件,這個類必須是EventDispatcher的子類,或實現了IEventDispathcer接口。
JAVA中,將產生某個事件的對象稱爲這個事件的source。但在Flex中,可以說所有的事件都是FlashPlayer產生的。FlashPlayer9對事件模型的實現是建立在W3C的DOM事件模型上的,一個事件的生命週期有三個階段:捕獲、target、bubbling。
capture:在這一階段,Flashplayer從display list的根開始檢查,一直到目標組件,來看看有沒有任何父組件對這一事件感興趣。默認情況下,目標組件的父組件會忽略這一事件。
target:在這一階段,事件對象的屬性將會設置至目標組件中,並且所有註冊的對這一事件的監聽器將會獲得這一事件對象。
bubbling:最後,事件流將會從目標對象沿原路返回到根層組件,並通知在capture階段確定的對這事件感興趣的對象。
但是用戶自定義的事件並不會經歷上述的三個階段,不過AS3開發者可以建立自定義的事件分派者來實現這三個階段。
例如下面的代碼:
<?xml version=”1.0” encoding=”utf-8”?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” >
<mx:Panel x=”17.5” y=”20” width=”209” height=”142” layout=”absolute”
click=”trace(‘click event in the Panel’)” title=”Just a Panel”>
<mx:Button label=”ClickMe” x=”60.5” y=”38”
click=”trace(‘click event in the Button’)”/>
</mx:Panel>
</mx:Application>
將會在控制檯輸出:
click event in the Button
click event in the Panel
默認情況下,在capture階段是不會執行事件的監聽器的,但是可以通過設置來讓監聽器在capture階段就被執行:myPanel.addEventListener(MouseEvent.CLICK, panelClickHandler, true);這裏第三個參數就是指明要在capture階段執行監聽器。如果註冊兩遍,一遍帶參數true,一遍不帶,那麼在capture階段和bubbling階段都會執行監聽器。
我們還可以阻止事件的分派:
private function panelClickHandler(event:MouseEvent) :void{
var badNews: Boolean = true; // a flag to emulate a bad situation
if (event.eventPhase == EventPhase.CAPTURING_PHASE){
trace (“Capturing phase: click event in the Panel”);
if (badNews){
trace (“Capturing phase: Bad news. Will not propagate click to Button”);
event.stopPropagation();
}
}else {
trace (“click event in the Panel”);
}
}
需要強調的是,一個組件並不是將事件發送到任何其他的組件。它僅僅是將這個“令人激動的新聞”廣播到事件分派器。如果有任何組件對處理這個事件有興趣的話,它必須爲這個事件註冊一個監聽器。
在MXML中使用自定義事件時,要使用元數據標籤:
<?xml version=”1.0” encoding=”utf-8”?>
<mx:Button xmlns:mx=”http://www.adobe.com/2006/mxml”
width=”104” height=”28” cornerRadius=”10” fillColors=”[#00ff00, #00B000]”
label=”Add Item” fontSize=”12” click=”greenClickEventHandler()”>
<mx:Metadata>
[Event(name=”addItemEvent”, type=”flash.events.Event”)]
</mx:Metadata>
<mx:Script>
<![CDATA[
private function greenClickEventHandler():void{
trace(“Ouch! I got clicked! Let me tell this to the world.”);
dispatchEvent(new Event(“addItemEvent”, true));// bubble to parent
}
]]>
</mx:Script>
</mx:Button>
在上面的代碼中,當點擊這個button時,這個組件會將自定義的addItemEvent事件分派到“外面的世界”,它不用知道其他的事情。下面一段代碼註冊了一個監聽器來監聽這個事件。
<mx:TextArea xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#ff0000" creationComplete="init()">
<mx:Script>
<![CDATA[
private function init():void{
parent.addEventListener("addItemEvent",addItemToCartEventHandler);
}
private function addItemToCartEventHandler(event:Event):void{
this.text+="Yes! Someone has put some item inside me, but I do not know what it is. /n";
}
]]>
</mx:Script>
</mx:TextArea>
然後在application中這樣寫:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:ctrl="controls.*" layout="vertical">
<ctrl:CustomEvent_LargeGreenButton addItemEvent="greenButtonHandler(event)"/>
<ctrl:CustomEvent_BlindShoppingCart width="350" height="150" fontSize="14"/>
<mx:Script>
<![CDATA[
private function greenButtonHandler(event:Event):void{
trace("Someone clicked on the Large Green Button!");
}
]]>
</mx:Script>
</mx:Application>
如果在JAVA中,這樣的代碼要寫成:
LargeGreenButton.addClickEventListener(
new XXXListener(){
public void action() {
這裏往ShoppingCart中添加物品;
}
});
這樣就把LargeGreenButton和ShoppingCart粘合起來了,FLEX裏就去掉了這種粘合。
========================================================================
Flex中的事件機制 <script></script> ofengofeng | 更新時間:2008-07-11 08:49:25 | 點擊數:685
一. 事件簡介
事件可以由外設觸發, 比如:鍵盤,鼠標, 也可能是外部輸入, 比如: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中定義:
public class MyComponent extends UIComponent
{
...
}
在MXML中定義:
[Event(name="DataChange", type="DataChangeEvent")]
</mx:Metadata>
DataChangeEvent事件參數的定義:
public class DataChangeEvent extends flash.events.Event
{
public function DataChangeEvent()
{
super("DataChange");
}
public var Data:Object;
}
在自定義控件中定義和觸發事件:
<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>
容器接收相關自定義控件事件:
<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>
其實自定義事件的現實也很簡單,但起着非常重要的作用;正是因爲有了事件的機制,使得大部分重複的功能抽取到自定義控件中,從而達到一個很高的代碼重用性。