Chapter 4: About Event--Using events

    在Flex中使用事件分爲兩步:第一步,在mxml中寫個方法或者在類中寫個類方法,這個方法也就是來響應事件的事件監聽器或者事件處理者。該方法經常訪問Event對象的一些屬性或者應用狀態的一些其他設置。該方法通常包括一個指定被傳進來的某種事件類型的參數。

下面的例子展示了一個簡單的事件監聽函數,當一個控件觸發了這個函數正在監聽的事件。

    

       正如你在例子中所看到,你可以用display list 對象通過addEventListener()方法來註冊一個方法。

      大多數Flex控件簡化了監聽器的註冊,通過在MXML標籤中來指定監聽器。例如,通過了<mx:Button>的click屬性來指定了事件監聽器而不是用addEventListener() 方法。

 

        
      這等價於上個例子中的 addEventListener()方法。可是最好還是練習使用addEventListener()方法。因爲這個方法能夠通過讓你設置優先級和捕獲的設置和使用event的常量,從而讓你有能更好的控制事件。 此外,如果你使用addEventListener()方法來添加事件監聽器,你可以通過 removeEventListener()方法來移除這個監聽器,如果你是在標籤中使用事件屬性的方式添加的事件監聽器,你不能使用

removeEventListener() 來移除這個監聽器。

       每次當一個控件產生一個事件時,Flex創建一個包含關於那個事件的信息Event對象,該信息中包括了事件的類型和派發該事件的控件的引用。爲了能夠使用這個Event對象,你指定它作爲事件處理方法的一個參數,如下面的例子。

 

      如果你想要在事件處理方法中訪問一個通過內嵌式寫法(就是直接寫在MXML標籤中)而出發的Event對象,你必須在MXML標籤中增加event關鍵字一遍Flex可以隱式的傳遞給事件處理方法。如下所示:
<mx:Button id="b1" label="Click Me" click="myEventHandler(event)"/>

      有時候你不需要在處理函數中使用event對象 ,下面的例子創建了兩個事件處理函數並用ComboBox控件註冊了它們,第一個函數

openEvt(),沒有任何參數。第二個 函數changeEvt(),有一個Event類型的參數,在函數內使用事件對象來訪問ComboBox控件的值和

selectedIndex

 

指定Event對象

       你爲監聽器函數指定一個Event類型的參數,如下
function myEventListener(e:Event):void { ... }

      可是如果你想訪問具體的派發事件的屬性時,你必須指定一個更具體的事件類型,例如ToolTipEvent 或者 KeyboardEvent,見下:

     In some cases, you must import the events class in your ActionScript block
Most objects have specific events that are associated with them, and most of them can dispatch more than one
type of event.
If you declare an event of type Event, you can cast it to a more specific type to access its event-specific properties.

      某些時候,你必須在Actionscript代碼塊中引入該事件類。大多數的對象都有和它們相關聯的事件,而且他們的當中的多數能派發一個以上的事件類型。

  

訪問event.currentTarget屬性

       Event對象包含了派發事件的組件的實例的引用,這意味着你可以在事件監聽函數中訪問該實例所有的屬性和方法。下面的例子展示了訪問出發事件的Button控件的id屬性。


     你可以訪問 currentTarget的成員。如果你不把currentTarget強制轉換成一個具體的類型,編譯器就把它作爲Object類型,Object可以有任何屬性和方法因爲在Actionscript中Object類是動態的。因此,當你訪問currentTarget的屬性和方法時,最好把它轉換爲你所認爲的將能派發事件的類型。這將在編譯期給你強類型檢查從而能幫助你避免在運行時拋出run-time異常。下面的例子在調用setSelection()方法前把currentTarget轉換爲TextInput類型,而在設置tmesis屬性前沒有強轉,tmesis屬性其實在TextInput類中不存在的。爲的是說明如果你沒有強轉的話,當你試圖訪問不存在的成員時你將會看到一個run-time異常而不是complie-time錯誤,而如果你把currentTarget轉換成一個具體的類型的話,類型檢查就會發生,就可以避免發生這種錯誤。

 


      你也可以把currentTarget強轉成UIComponent或者一些其他的泛類,這些類仍然有display objects的方法。通過這種方式,即使你不確切的知道哪個控件將會派發出事件,至少你可以確保有些類型檢查。

你也可以訪問這個包含當前節點的引用的target屬性的屬性和方法, (沒明白什麼意思。。。。。。。)

 

註冊事件監聽函數

有許多方式註冊事件監聽器。

1、寫死式(哈哈)
 

2 、用addEventListener()方法

      正如以前的例子,不論用戶什麼時候單機這個Button按鈕,Flex都將調用myClickHandler()函數。可是,用這種方法註冊監聽器提供了更多的靈活性。你可以爲一個事件監聽器註冊多個組件,一個組件添加多個事件監聽器,或者移除它們。
3 、 創建一個事件監聽類,用這個類來監聽該組件的事件。這種方法提高了代碼的重用性,使你能夠在MXML文件外集中處理事件。

 


 

在標籤中定義event事件監聽器

在Flex應用中定義事件監聽器的最簡單的方法是在組件的MXML標籤中指定一個事件監聽函數。在一個組件的事件屬性中加上Actionscript語句或者指定一個事件處理函數。

事件處理函數可以包含任何有效的Actionscript代碼, 可以包含全局的方法,如下例:


在寫死式中有一個特殊的參數, event參數。如果你把event加入到參數列表,Flex會傳遞這個event對象,在你的事件監聽器中可以訪問這個event對象的所有屬性,下面的例子把event傳遞到submitForm()函數中,然後把它具體化爲MouseEvent類型。



      

      當你使用寫死式的方式添加事件監聽函數時,在傳遞參數時最好還是把event這個關鍵字傳過去,並且在事件監聽函數的參數類型中指明一個最準確的Event類型,比如用MouseEvent而不用Event。你可以使用event對象來訪問事件源的引用,事件的類型(比如click)或者其他相關的屬性。比如是一個list-based控件的話可以訪問它的row number和值。你也可以使用event對象來訪問事件源組件的屬性和方法。儘管你大多數時候是將整個Event對象傳遞給事件監聽函數,你也可以傳遞event的某個單獨的屬性,如下例子:

     

      使用寫死式這種方式沒有使用addEventListener()方法靈活。缺點是你不能給event對象設置useCapture或者priority屬性並且一旦你添加之後,你將不能移除它。

 


使用addEventListener() 方法


b1.addEventListener(MouseEvent.CLICK, myClickListener);

addEventListener() 方法通常格式如下:

        

        event_type該參數是組件派發的事件類型。它可以是事件類型的字符串(比如"click"或者"mouseOut")也可以是一個靜態常量(比如MouseEvent.CLICK 或者 MouseEvent.MOUSE_OUT)。這個參數是必須的。
      

       靜態常量提供了指定事件類型的更簡單的方式,你應該使用常量而不是字符串因爲如果你一不小心拼錯了常量的名字編譯器會捕捉到錯誤,但是如果你寫錯了字符串的話屬於書寫上的錯誤,調試會更加困難並且可能導致意外的行爲。 
       You should use the constants wherever possible. For example, when you are testing to see whether an Event object 
is of a certain type, use the following code:


if (myEventObject.type == MouseEvent.CLICK) {/* your code here */}
     Do not use the following code:
if (myEventObject.type == "click") {/* your code here */}

 


    The event_listener argument is the function that handles the event. This argument is required.use_capture parameter of the addEventListener() method lets you control the phase in the event flow in which your listener will be active. It sets the value of the useCapture property of the Event object. If useCapture is set to true, your listener is active during the capturing phase of the event flow. If useCapture is set to false, your listener is active during the targeting and bubbling phases of the event flow, but not during the capturing phase. The default value is determined by the type of event, but is false in most cases. addEventListener() twice, once with the To listen for an event during all phases of the event flow, you must call useCapture parameter set to true, and again with use_capture set to false. This argument is optional.

      addEventListener() 的use_capture參數讓你可以控制監聽器在事件流中的3個時期何時應該被觸發。如果useCapture屬性設置爲true,事件監聽函數在事件流的捕獲階段被觸發,如果useCapture被設置爲false,事件監聽器將會在目標和冒泡階段被觸發,默認值取決於該事件類型,但是大多數時候默認值是false,

爲了監聽事件流的所有階段,你必須把useCapture設置爲true,然後重新把use_capture設置爲false,
      

        priority參數設置了事件監聽器的優先級,對於同一個事件來說,數字越高,相當於其他的執行的越早。同一優先級按照它們被添加的順序依次執行,priority參數默認值爲0,但是你可以給它賦值爲負數或正數,如果幾個事件監聽函數沒有設置優先級而被添加進去,越早被添加的執行的越早。
         

        weakRef屬性爲你提供了控制內存資源的功能,強引用(當weakRef是false時)可以避免監聽器被垃圾回收。若引用(當weakRef是true時)則相反,默認值是false,當你添加了一個監聽函數並且該函數被喚醒時,Flex隱式的創建Event對象然後把它傳遞給監聽函數,你必須在函數聲明時定義該參數。


b1.addEventListener(MouseEvent.CLICK, performAction);


In the listener function, you declare the Event object as a parameter, as follows:


public function performAction(e:MouseEvent):void {
...
}

       
       The following example defines a new handler function myClickListener(). It then registers the click event of the Button control with that handler. When the user clicks the button, Flex calls the myClickHandler() function.

 

 

 

 


 

Using addEventListener() inside an MXML tag
You can add event listeners with the addEventListener() method inline with the component definition. The following Button control definition adds the call to the addEventListener() method inline with the Button controls initialize property:

MXML標籤中使用addEventListener()方法

可以在組件的定義中使用addEventListener()添加事件監聽器,下面的例子在Button控件的initialize屬性中調用addEventListener()方法添加監聽器,

 這等價於寫死式,可是用addEventListener()可以讓你設置useCapture and priority屬性,此外寫死式不能移除監聽器,可是用addEventListener()方式可以移除。

 


 

Using nested inner functions as event listeners
Rather than passing the name of an event listener function to the addEventListener() method, you can define
an inner function (also known as a closure).
In the following example, the nested inner function is called when the button is clicked:
<
Function closures are created any time a function is executed apart from an object or a class. They retain the scope
in which they were defined. This creates interesting results when a function is passed as an argument or a return
value into a different scope. For example, the following code creates two functions: 
foo(), which returns a nested function named rectArea() that calculates the area of a rectangle, and bar(), which calls foo() and stores the returned function closure in a variable named myProduct. Even though the bar() function defines its own local variable x (with a myProduct() is called, it retains the variable x (with a value of 40) defined 
value of 2), when the function closure in function foo(). The bar() function therefore returns the product of the numbers in the TextInput controls, rather than 8.

If the listener that you pass to addEventListener() method is a nested inner function, you should not pass true
useWeakReference argument. For example:
for the
addEventListener("anyEvent",
function(e:Event) { /* My listener function. */ },
false, 0, true);
In this example, passing true as the last argument can lead to unexpected results. To Flex, an inner function is
actually an object, and can be freed by the garbage collector. If you set the value of the
useWeakReference
argument to
true, as shown in the previous example, there are no persistent references at all to the inner function.
The next time the garbage collector runs, it might free the function, and the function will not be called when the
event is triggered.
If there are other references to the inner function (for example, if you saved it in another variable), the garbage
collector will not free it.
Regular class-level member functions are not subject to garbage collection; as a result, you can set the value of the
useWeakReference argument to true and they will not be garbage collected.
Removing event handlers
It is a good idea to remove any handlers that will no longer be used. This removes references to objects so that they
can be cleared from memory. You can use the
removeEventListener() method to remove an event handler that
you no longer need. All components that can call
addEventListener() can also call the
removeEventListener() method. The syntax for the removeEventListener() method is as follows:
componentInstance.removeEventListener(event_type:String, listener_function:Function,
use_capture:Boolean)
For example, consider the following code:
myButton.removeEventListener(MouseEvent.CLICK, myClickHandler);
The event_type and listener_function parameters are required. These are the same as the required param-
eters for the
addEventListener() method.
use_capture parameter is also identical to the parameter used in the addEventListener() method. Recall
The
that you can listen for events during all event phases by calling
addEventListener() twice: once with
use_capture set to true, and again with it set to false. To remove both event listeners, you must call
removeEventListener() twice: once with use_capture set to true, and again with it set to false.
addEventListener() method in an ActionScript
You can remove only event listeners that you added with the
block. You cannot remove an event listener that was defined in the MXML tag, even if it was registered using a
call to the
addEventListener() method that was made inside a tag attribute.
The following sample application shows what type of handler can be removed and what type cannot:

 


Creating event handler classes
You can create an external class file and use the methods of this class as event handlers. Objects themselves cannot
be event handlers, but methods of an object can be. By defining one class that handles all your event handlers, you
can use the same event handling logic across applications, which can make your MXML applications more readable and maintainable.
To create a class that handles events, you usually import the flash.events.Event class. You also usually write an empty constructor. The following ActionScript class file calls the Alert controls show() method whenever it handles an event with the handleAllEvents() method:

創建一個事件處理類

你可以創建一個外部類文件,把它當中的方法作爲事件處理函數,對象本身並不能作爲事件處理函數,但是對象的方法可以。通過定義一個類來處理你的所有的事件處理函數,可以在整個應用中應用同一個事件處理邏輯,這將會使你的MXML應用可讀性和維護性帶來提升。

創建一個這樣的類,通常是引入flash.events.Event類,然後寫一個空的構造函數,下面的類文件每當它的handleAllEvents() 方法處理一個事件時,都會調用Alert的show()方法,
/
      In your MXML file, you declare a new instance of MyEventHandler and use the addEventListener() method to register its handleAllEvents() method as a handler to the Button controls click event, as the following example shows:

      在你的XMML文件中,你可以定義一個MyEventHandler類的實例,用addEventListener()方法來註冊它當中的handleAllEvents() 方法作爲Buttion控件的click事件的事件監聽函數。如下例子所示:

       The best approach is to define the event handlers method as static. When you make the event handler method
static, you are not required to instantiate the class inside your MXML application. The following
createHandler() function registers the handleAllEvents() method as an event handler without instantiating
the MyStaticEventHandler class:

      最好是把類中的想要作爲事件監聽器的方法定義爲static,好處是在MXML應用中不需要實例化這個類,下面的createHandler() 方法註冊了handleAllEvents()作爲事件監聽器,而沒有實例化這個MyStaticEventHandler類,

Store your event listener class in a directory in your source path. You can also store your ActionScript class in the
same directory as your MXML file, although Adobe does not recommend this.

 



爲一個事件註冊多個事件監聽器

       你有兩種方式來爲一個事件註冊多個事件監聽器,當你用寫死式的方法來註冊多個監聽器的時候,可以用“;”分號把他們隔開,下面的例子展示了爲click事件註冊了submitForm() 和 debugMessage()這兩個函數,

      通過調用addEventListener()方式,可以多次調用addEventListener()方法來添加多個處理函數。下面的例子爲b1s的click事件住了submitForm() and debugMessage()監聽方法,


     你可以結合起來使用這兩種方法,下面的例子展示了 :爲一個Button控件通過寫死式註冊了一個click事件監聽函數 performAction(),在performAction()方法中,按照CheckBox控件的狀態條件給它添加了第二個click事件監聽器logAction(),

You can set the order in which event listeners are called by using the priority parameter of the
addEventListener() method. You cannot set a priority for a listener function if you added the event listener
using MXML inline. For more information on setting priorities, see Event priorities– on page .

 

給多個組件註冊同一個事件監聽器

你可以給同一個組件的多個事件或者不同組件的多個事件註冊同一個事件監聽器,下面的例子給兩個不同的button註冊了一個監聽函數submitForm():

       當你用addEventListener() 方法來爲多個組件的事件註冊同一個事件監聽器的時候,你必須爲每一個組件的實例都調用addEventListener() 方法。如下:

      

       如果你這樣做的話,你應該在事件監聽函數中加上處理事件類型的邏輯代碼,事件源的引用已經被添加在了Event對象上了,不管什麼觸發的這個事件,你都能基於Event對象的target或者type屬性來條件化事件處理的過程。Flex在所有的event對象上都添加上了這兩兩個屬性,下面的例子爲Button的click事件和CheckBox的click事件註冊了myEventHandler()事件監聽函數,爲了發現調用該事件監聽的對象類型,函數中用case語句檢查event對象的中的target的className屬性。



 

給監聽函數傳遞額外的參數

能不能給監聽函數傳遞額外的參數取決你是怎樣註冊它的,如果你是用addEventListener()方法註冊的,你不能給它傳遞多餘的參數,而且那個事件監聽函數只可以聲明一個參數,就是Event對象(或者它的子類),舉個例子,下面的例子將會報錯因爲 clickListener()方法需要傳遞兩個參數。

 



      

     因爲addEventListener() 方法的第二個參數是個function類型,所以你不能在調用addEventListener() 時爲那個函數具體指定參數,爲了能夠傳遞更多的參數給監聽函數,你必須在監聽函數中已經聲明瞭它們,然後then call the final method with those parameters. 如果你是通過寫死式註冊了事件監聽器,你可以給它傳遞任意多個參數,只要你在定義監聽函數的時候參數列表中已經聲明瞭它們,就可以傳遞,下面的例子給runMove()監聽函數傳遞了一個字符串。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章