官术网_书友最值得收藏!

第5章 事件的發送和處理

事件處理系統是交互式程序設計的重要基礎。利用事件處理機制,可以方便地相應用戶輸入和系統事件。ActionScript 3.0的事件機制基于文檔對象模型(DOM3),是業界標準的事件處理體系結構。使用機制不僅方便,而且符合標準。ActionScript 3.0全新的事件處理機制是ActionScript編程語言中的重大改進,對ActionScript程序設計人員來說,在使用上也更加的方便和直觀。

5.1 事件處理基礎

本節將介紹事件和處理的基本概念,了解常見的事件處理任務。對照ActionScript編程語言中不同版本的事件處理機制的異同,明確ActionScript 3.0中事件處理機制具有良好的性能。

5.1.1 事件和事件處理基礎知識

事件和事件處理是面向對象編程的基礎。本小節將介紹事件和事件處理的基礎知識以及事件處理的方法和事件處理的任務。

1. 事件和事件處理基本概念

在宏觀的對象上,事件指的是當前所發生的事情。比如人,人要張口吃飯,張口是一個動作,也就是當前發生了一個張口事件,這個事件的結果是吃飯。編程語言中的事件,和宏觀對象的事件類似,同樣指當前程序所能接收到的當前所發生的事情。比如,現在單擊了一下鼠標,也就是發生了單擊鼠標這一狀況,而這一狀況就被稱為發生了鼠標單擊事件。

事件處理是指在發生了某個事件之后,需要怎么樣來應對,下一步要做什么。還以“張口”這一事件為例,口張開了,下面將要發生的事情可能有多種,比如吃飯、呼吸等,那么需要有下一步的動作提示,才能繼續下去,所以才有了張口吃飯這一完整的動作。同樣,在發生了鼠標單擊動作之后,需要指出下一步要做什么,是輸出一段文字,還是開始播放一段動畫,這就需要進行事件處理,實現在發生事件后下一步的動作。用于處理事件的函數或方法,習慣上稱為事件偵聽器或事件偵聽函數。

張口吃飯,是因為感覺到了“張口”這一動作,才了解發生了這一事件。在編程的過程中,要了解當前是不是發生了事件,發生了什么事件,需要使用事件偵聽來完成。事件偵聽的目的就是為了了解當前有哪些事件發生,發生了什么狀況。

張口吃飯,感覺到了“張口”這一動作,而這一感覺來自于神經系統,是對“口”進行神經分析的結果。與此類似,要知道程序中的某個對象發生了某個事件,就要給這個對象加上一個控制神經,即事件偵聽,使得系統能夠了解事件的發生。給對象添加事件偵聽的過程,在編程語言中習慣稱為在某個對象上注冊某個事件偵聽函數。

2. ActionScript 3.0中的事件和事件處理

ActionScript編程語言支持各種類型的交互操作,能夠接受各種不同的事件。無論是響應鼠標單擊、敲擊鍵盤這些簡單的操作,還是接受和處理文本框中輸入的數據這樣復雜的用戶交互,與SWF文件進行的任何類型的交互操作都可以被視為事件。即使在沒有用戶操作的情況下也有可能發生事件。比如從后臺加載完數據或者接受了一個遠程的連接要求等。

在ActionScript 3.0中,每一個事件都用一個事件對象來表示。事件對象是Event(事件)類或者Event類的子類的實例。事件對象用于存儲特定的事件信息,包含操作對象的方法。比如當Flash Player監測到用鍵盤操作時,就會創建一個KeyboardEvent(鍵盤事件)事件對象實例,用于記錄該鍵盤操作事件。

創建事件對象后,Flash Player就會“調度”該事件對象,將該事件對象傳遞給作為事件目標的對象。比如Flash Player監聽到鍵盤輸入操作后,創建的事件對象就會被傳遞到對應的事件目標對象對事件進行處理。

在ActionScript 3.0中,可以通過事件偵聽器來“偵聽”代碼中的事件對象。“事件偵聽器”是用戶自己編寫的用于響應特定事件的函數或者方法。需要將事件偵聽器添加到事件目標,或者添加到作為事件對象事件流的一部分顯示對象列表,才能實現程序響應事件。比如要監聽鍵盤操作的事件對象,需要實現把事件偵聽器注冊到Stage對象上。

編寫事件偵聽器代碼的語法格式如下:

    function事件偵聽函數(事件對象:事件類型):void{
          //此處是為響應事件而執行的動作
    }
    事件目標.addEventListener(事件對象的事件名稱 事件偵聽函數);

說明

此段代碼執行兩個操作,一是定義一個函數,指定為響應事件而執行的動作或者方法;另一個是為指定事件“注冊”該函數,當該事件發生時,執行該函數的動作。

要創建自己的事件偵聽器,需要注意以下格式說明。

?事件偵聽函數:指定響應事件要執行的動作或方法。

?事件對象:要偵聽的事件所調度的事件對象指定相應的類名稱。

?事件目標:被偵聽的目標對象名稱。

?事件對象的事件名稱:在事件對象類中具體的事件常量。

3. ActionScript 3.0中的事件處理任務

在ActionScript 3.0編程過程中,常見的使用事件處理的任務有:

?編寫代碼以響應事件。

?阻止代碼響應事件。

?處理事件對象。

?處理事件流。

?從類中調度事件。

?創建自定義事件類型。

5.1.2 早期 ActionScript 版本中的事件處理

ActionScript 1.0使用on()和onClipEvent()兩個事件處理函數來處理事件。具體包括:

?on()事件處理函數,直接放在按鈕或者影片剪輯實例上。

?onClipEvent()處理函數,直接放在影片剪輯實例上。

這種方法把代碼直接加在實例上,簡單、方便、直接,但是由于分散在各個不同的元件之上,難以管理和維護。特別是處理不是本人編寫的代碼時,查看和找尋會浪費太多的寶貴時間。

在ActionScript 2.0中對事件處理進行了改進,增加了一些事件處理機制,具體為:

?回調函數事件:onload、oninit、onComplete等。

?事件偵聽器:addListener()、addEventListener()。

特別是增加的事件偵聽機制,已經實現了ActionScript 3.0的部分功能。但是在ActionScript 2.0中還存在著很多的不足,給開發人員造成了很大的困擾,比如下面的幾個方面。

?ActionScript 2.0中只有組件(UIComponent)類才有內置事件,其核心類和Flash API都沒有內置事件。

?事件偵聽器的注冊方式也有兩種:一種是addListener();一種是addEventListener()。使用起來容易造成混淆。

?ActionScript 2.0中關鍵字this的含義在各個事件處理系統中并不一致,造成this關鍵字指向不明確。

5.1.3 ActionScript 3.0中的事件處理

在ActionScript 3.0引入了基于文檔對象模型(DOM3)唯一的一種事件處理模式,取代了以前各版本中存在的眾多的事件處理機制。在ActionScript 3.0中只存在一種事件處理模型,雖然會對一些老版本的用戶和一些非開發者造成一定的麻煩,但更加清晰,更加標準,更符合面向對象開發的需要。

對比ActionScript 2.0,ActionScript 3.0的事件處理體系具有以下幾個新特點:

?在ActionScript 3.0中,只能使用addEventListener()注冊偵聽器。

?在ActionScript 3.0中,可以對屬于事件流部分的任何對象調用addEventListener()方法。

?在ActionScript 3.0中,只有函數或方法可以是事件偵聽器。

5.2 Event類

在ActionScript 3.0的事件處理系統中,事件對象主要有兩個作用:一是將事件信息儲存在一組屬性中,來代表具體事件;二是包含一組方法,用于操作事件對象和影響事件處理系統的行為。

ActionScript 3.0中,在Flash播放器的應用程序接口中,有一個Event類,作為所有事件對象的基類,也就是說,程序中所發生的事件都必須是Event類或者其子類的實例。

5.2.1 了解Event類的屬性

Event類公開的屬性有type、cancelable、target、currentTarget、eventphase、bubles。

1. type屬性

每個事件對象都有關聯的事件類型。事件類型存儲以字符串的形式存儲在Event.type屬性中。利用事件類型,可以區分不同類型的事件。比如下面的代碼說明給clickHandler()偵聽器函數響應傳遞給myobj的任何鼠標單擊事件對象。

    myobj.addEventListener(MouseEvent.CLICK,clickHandler);

事件類型與Event類自身關聯并由Event類常數表示,在Event類中存在二十多種事件類型常量。利用這些常數可以引用特定的事件類型,使用時要使用這些常數而不是它所代表的字符串。如果在使用時輸入了錯誤的常數名稱,編譯器會報錯。但是如果不使用常量而使用字符串,編譯時可能不會提示錯誤名稱,而可能會導致難以調試的意外情況。比如添加事件偵聽器時,請使用以下代碼:

    myobj. addEventListener(MouseEvent.CLICK,clickHandler);

而不是ActionScript 2.0中的代碼:

    myobj. addEventListener("click", clickHandler);

注意 事件的類型是區分大小寫的。

2. cancelable屬性

事件的默認行為是否可以被阻止由布爾值表示,并存儲在Event.cancelable屬性中。此屬性是一個布爾值,默認為false。這個屬性一般是和preventDefault()方法結合在一起使用的。

3. target屬性

target屬性用于存儲對事件目標的引用。下面先生成一個顯示(sprite)對象sp,然后給其注冊一個鼠標單擊事件,單擊之后,使用target屬性實現對顯示對象的引用,并使sp的位置發生改變。代碼如下所示:

    //定義一個變量,使用繪圖對象創建一個圓
    var sp:Sprite=new Sprite();
    sp.graphics.beginFill(0xff0000);
    sp.graphics.drawCircle(100,100,40);
    sp.graphics.endFill();
    //把圓加入舞臺中
    addChild(sp);
    //創建事件偵聽函數
    function TestTar(event:MouseEvent):void {
          //通過獲取目標,跳轉對象位置
          event.target.x=300;
          event.target.y=100;
    }
    //注冊事件偵聽
    sp.addEventListener(MouseEvent.CLICK,TestTar);

完成后的效果如圖5.1所示。

圖5.1 事件目標效果圖

4. 其他屬性

currentTarget、eventphase和bubbles這3個屬性都和ActionScript 3.0的事件流機制有關,在平時用到的不多。

要注意的是,實例屬性全部是只讀屬性[read-only]。這些屬性是使用getter方法實現的,并不是真正的實例屬性。

Event類還有26個靜態字符串常量,定義了26種事件類型。其中包括:“ADDED”表示對象被添加到顯示列表時發送事件;“REMOVED”表示對象從顯示列表被移除時發送事件;“UNLOAD”表示對象被卸載時發送事件。

5.2.2 了解Event類的方法

Event類的方法有7種:clone()、toString()、stopPropogation()、stopImmediatePropogation()、preventDefault()、isDefaultPrevented()和formatToString()。這些方法的用途如下:

?Event.clone()方法用于賦值Event子類實例,返回Event對象原始實例的副本。當需要自定義Event子類時,就必須要繼承Event.clone()方法,用于賦值自定義類的屬性。另外還要加上新的屬性,否則在偵聽器重寫調用時,這些屬性的值會出現錯誤。

?Event.toString()屬性返回一個包含Event對象的所有屬性的字符串。如果要自定義事件類,那么重寫toString()方法時,可以使用formatToString()這個方法在返回的字符串中加入新的事件實例屬性。

?Event.stopPropogation()方法可阻止事件對象移動到下一個節點,但只有在允許執行當前節點上的任何其他事件偵聽器之后才起作用。

?Event.stopImmediatePropogation()方法也阻止事件對象移動到下一個節點,但不允許執行當前節點上的任何其他事件偵聽器。

?Event.preventDefault()、Event.isDefaultPrevented()和Event.cancelable屬性結合使用,用于取消事件的默認行為的發生。

5.2.3 Event類的子類

對于很多事件來說,使用Event類的一組屬性就已經足夠了。但是,Event類中的屬性無法捕獲其他事件具有的獨特的特性,比如鼠標的單擊事件、鍵盤的輸入事件等。ActionScript 3.0的應用程序接口特意為這些具有顯式特征的事件準備了Event類的幾個子類。這些子類主要包括:

?鼠標類:MouseEvent。

?鍵盤類:KeyBoardEvent。

?時間類:TimerEvent。

?文本類:TextEvent。

每個子類定義了對于該種事件類別來說唯一的附加屬性和事件類型。比如,與鼠標輸入相關的事件具有若干獨特的特性,無法被Event類中定義的屬性捕獲。MouseEvent類則添加了10個屬性,擴展了Event類。這10個屬性包含諸如鼠標事件的位置和在鼠標事件過程中是否按下了特定鍵等信息。

Event子類還增加了代表與子類關聯的事件類型的常量。例如,MouseEvent類定義幾種鼠標事件類型的內容,包括click、doubleClick、mouseDown和mouseUp事件類型。

當然,有時可能需要在事件對象中加入額外的屬性或方法時,這就需要自定義事件類。

關于這些子類的用法,后面的章節會逐步講述。

5.3 事件偵聽器

事件偵聽器也就是以前版本中的事件處理函數,是事件的處理者,負責接收事件攜帶的信息,并在接收到該事件之后執行事件處理函數體內的代碼。

添加事件偵聽的過程有兩步:第一步是創建一個事件偵聽函數;第二步是使用addEventListener()方法在事件目標或者任何顯示對象上注冊偵聽器函數。

5.3.1 創建事件偵聽器

事件偵聽器必須是函數類型,可以是一個自定義的函數,也可以是實例的一個方法。創建偵聽器的語法格式如下:

    function 偵聽器名稱(evt:事件類型):void{...}

語法格式說明如下:

?偵聽器名稱:要定義的事件偵聽器的名稱,命名需符合變量命名規則。

?evt:事件偵聽器參數,為必需。

?事件類型:Event類實例或其子類的實例。

?void:返回值必須為空,不可省略。

下面代碼創建一個顯示紅色圓形的簡單SWF文件,并使用名為Test()的偵聽器函數偵聽紅色圓形上的鼠標單擊事件。代碼如下所示:

    //定義一個變量,使用繪圖對象創建一個圓
    var sp:Sprite=new Sprite();
    sp.graphics.beginFill(0xff0000);
    sp.graphics.drawCircle(100,100,40);
    sp.graphics.endFill();
    //把圓加入舞臺中
    addChild(sp);
    //創建事件偵聽函數
    function Test(event:MouseEvent):void {
          trace("事件偵聽函數建立成功!")
    }
    //注冊事件偵聽器
    sp.addEventListener(MouseEvent.CLICK,Test);

說明

在顯示的紅色圓形上單擊鼠標,輸出為“事件偵聽函數建立成功!”,說明事件偵聽器建立成功。

完成后的效果如圖5.2所示。

圖5.2 注冊事件偵聽測試

ActionScript 3.0主要是面向對象的編程而設計,所以事件偵聽函數同樣可以為類方法。把代碼寫成文檔類可以實現相同的效果。代碼如下所示:

    //創建包
    package Lzxt {
          //導入包Sprite
          import flash.display.Sprite;
          //創建類
          public class Test extends Sprite {
                //構造函數
          public function Test() {
                //創建對象
          var sp:Csp = new Csp();
                //加入對象
          addChild(sp);
                }
          }
    }
    //包外類,用于創建對象
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    class Csp extends Sprite {
            public function Csp() {
                //使用繪制方法繪制圓形
                graphics.beginFill(0xFF0000);
                graphics.drawCircle(100,100,40);
                graphics.endFill();
                //至此事件偵聽
                addEventListener(MouseEvent.CLICK, testclick);
        }
            //創建事件偵聽函數
            private function testclick(event:MouseEvent):void {
                trace("類方法實現事件處理函數");
        }
    }

說明

在顯示的紅色圓形上單擊鼠標,輸出為“類方法實現事件處理函數”,說明事件偵聽器建立成功。

完成后的效果如圖5.3所示。

圖5.3 類方法實現事件偵聽效果

5.3.2 管理事件偵聽器

在ActionScript 3.0中使用IEventDispatcher接口的方法來管理偵聽器函數,主要用于注冊、檢查和刪除事件偵聽器。

1. 注冊事件偵聽器

addEventListener()函數用來注冊事件偵聽函數。注冊偵聽器的語法格式如下:

    事件發送者.addEventListener(事件類型,偵聽器);

語法格式說明如下:

?事件發送者:其必須為EventDispatcher類或子類的實例。

?事件類型:Event類實例或其子類的實例。

?偵聽器:事件執行時的偵聽器函數,注意,此數的函數不要函數名后的括號。

下面代碼示例把Test()函數注冊為sp對象的偵聽器,接收鼠標單擊事件:

    sp.addEventListener(MouseEvent.CLICK,Test);

注意下面的注冊語句是錯誤的:

    sp.addEventListener(MouseEvent.CLICK,Test());

2. 刪除事件偵聽器

removeEventListener()函數用來刪除事件偵聽器函數。刪除偵聽器的語法格式如下:

    事件發送者.removeEventListener(事件類型,偵聽器);

事件發送者、事件類型和偵聽器的要求與注冊事件偵聽器的要求相同,不再贅述。

將不再使用的所有偵聽器刪除可以節約系統資源,提高程序效率。下面代碼創建一個顯示紅色圓形的簡單SWF文件。名為Test()的偵聽器函數偵聽紅色圓形上的鼠標單擊事件,當單擊之后,刪除事件偵聽器。代碼如下所示:

    //定義一個變量,使用繪圖對象創建一個圓
    var sp:Sprite=new Sprite();
    sp.graphics.beginFill(0xff0000);
    sp.graphics.drawCircle(100,100,40);
    sp.graphics.endFill();
    //把圓加入舞臺中
    addChild(sp);
    //創建事件偵聽函數
    function Test(event:MouseEvent):void {
          trace("事件偵聽函數建立成功!")
          //移除事件偵聽函數
    sp.removeEventListener(MouseEvent.CLICK,Test);
    }
    //注冊事件偵聽函數
    sp.addEventListener(MouseEvent.CLICK,Test);

說明

在顯示的紅色圓形上單擊鼠標,輸出為“事件偵聽函數建立成功!”,說明事件偵聽器建立成功,再次單擊,沒有任何輸出,說明事件偵聽器已經被刪除。

3. 檢查事件偵聽器

HasEventListener()方法和willTragger()方法,都可以用來檢測當前的事件發送者注冊了何種事件類型的偵聽器。

檢查事件偵聽器語法格式如下:

    事件發送者.hasEventListener(事件類型);

繼續使用上面的效果,在鼠標單擊紅色圓形之前檢查一次事件偵聽器,并在單擊之后再檢查一次事件偵聽器。代碼如下所示:

    //定義一個變量,使用繪圖對象創建一個圓
    var sp:Sprite=new Sprite();
    sp.graphics.beginFill(0xff0000);
    sp.graphics.drawCircle(100,100,40);
    sp.graphics.endFill();
    //把圓加入舞臺中
    addChild(sp);
    //創建事件偵聽函數
    function Test(event:MouseEvent):void {
          trace("事件偵聽函數建立成功!");
          //移除事件偵聽
          sp.removeEventListener(MouseEvent.CLICK,Test);
          trace(sp.hasEventListener(MouseEvent.CLICK));
    }
    //注冊事件偵聽
    sp.addEventListener(MouseEvent.CLICK,Test);
    trace(sp.hasEventListener(MouseEvent.CLICK));

代碼執行后的輸出結果如下所示:

    true
    事件偵聽函數建立成功!
    false

說明

從輸出結果可以看出,在刪除事件偵聽器之前,該事件存在,輸出為true,當刪除之后,輸出為false。

willTrigger()方法同樣也可以檢查事件偵聽器。willTrigger()不但會檢查該顯示對象上的偵聽器,還會檢查該顯示列表對象在事件流所有階段中的所有父級上的偵聽器。

下面的代碼先建立一個紅色的圓形,然后在紅色圓形中建立一個黃色的小圓形,名為Test()的偵聽器函數偵聽紅色圓形上的鼠標單擊事件,最后檢查黃色圓形上的事件偵聽器。代碼如下所示:

    //定義一個變量,使用繪圖對象創建一個圓
    var sp:Sprite=new Sprite();
    sp.graphics.beginFill(0xff0000);
    sp.graphics.drawCircle(100,100,40);
    sp.graphics.endFill();
    //把圓加入舞臺中
    addChild(sp);
    //創建另一個對象
    var spp:Sprite=new Sprite();
    spp.graphics.beginFill(0xffff00);
    spp.graphics.drawCircle(100,100,20);
    spp.graphics.endFill();
    sp.addChild(spp);
    //創建事件偵聽函數
    function Test(event:MouseEvent):void {
          trace("事件偵聽函數建立成功!");
    }
    //注冊事件偵聽函數
    sp.addEventListener(MouseEvent.CLICK,Test);
    trace(spp.hasEventListener(MouseEvent.CLICK));
    trace(spp.willTrigger(MouseEvent.CLICK));
    /*
    輸出為:
    false
    true
    */

說明

輸出的結果可以說明hasEventListener()方法只能檢測指定的顯示對象上的事件偵聽器,而willTrigger()方法還可以檢查該顯示對象父級上的顯示對象。

5.4 事件處理類型

ActionScript 3.0使用單一事件模式來管理事件,所有的事件都位于flash.events包內,其中構建了二十多個Event類的子類,用來管理相關的事件類型。本節介紹常用的鼠標事件(MouseEvent)類型、鍵盤事件(KeyboardEvent)類型和時間事件(TimerEvent)類型和幀循環(ENTER_FRAME)事件。

5.4.1 鼠標事件

在ActionScript 3.0之前的語言版本中,常常使用on(press)或者onClipEvent(mousedown)等方法來處理鼠標事件。而在ActionScript 3.0中,統一使用MouseEvent類來管理鼠標事件。在使用過程中,無論是按鈕還是影片事件,統一使用addEventListener注冊鼠標事件。此外,若在類中定義鼠標事件,則需要先引入(import)flash.events.MouseEvent類。

MouseEvent類定義了10種常見的鼠標事件,具體如下:

?CLICK:定義鼠標單擊事件。

?DOUBLE_CLICK:定義鼠標雙擊事件。

?MOUSE_DOWN:定義鼠標按下事件。

?MOUSE_MOVE:定義鼠標移動事件。

?MOUSE_OUT:定義鼠標移出事件。

?MOUSE_OVER:定義鼠標移過事件。

?MOUSE_UP:定義鼠標提起事件。

?MOUSE_WHEEL:定義鼠標滾軸滾動觸發事件。

?ROLL_OUT:定義鼠標滑入事件。

?ROLL_OVER:定義鼠標滑出事件。

下面通過幾個范例來說明這些鼠標事件的使用方法,并解決從ActionScript 2.0到ActionScript 3.0過程中一些原有實現方法的轉換。

范例一:給顯示對象添加鼠標單擊事件

下面先建立一個簡單按鈕,把名為click的事件偵聽器注冊到按鈕上,執行鼠標單擊事件,按鈕上的文字提示“你單擊了按鈕”。代碼如下所示:

    //創建矩形作為按鈕背景
    var sp:Sprite=new Sprite();
    sp.graphics.beginFill(0xff0000);
    sp.graphics.drawRect(0,0,100,20);
    sp.graphics.endFill();
    addChild(sp);
    //創建按鈕上的文本
    var label:TextField=new TextField();
    label.text="單擊按鈕";
    sp.addChild(label);
    //創建單擊事件處理函數
    function click(event:MouseEvent):void {
          //單擊后改變的文字內容
          label.text="你單擊了按鈕";
    }
    //注冊鼠標單擊事件
    sp.addEventListener(MouseEvent.CLICK,click);

完成后的效果如圖5.4所示。

圖5.4 單擊效果圖

范例二:給顯示對象添加鼠標雙擊事件

鼠標雙擊事件和單擊事件的使用方法相同,但是,系統默認鼠標雙擊事件并沒有打開,需要把鼠標雙擊屬性(double-ClickEnabled)打開,否則即使執行了雙擊操作,按鈕也不會響應操作。

下面同樣建立一個簡單按鈕,把名為dbclick的事件偵聽器注冊到按鈕上,雙擊按鈕,按鈕上的文字變為“你雙擊了按鈕”。代碼如下所示:

    //創建按鈕背景
    var sp:Sprite=new Sprite();
    sp.graphics.beginFill(0xff0000);
    sp.graphics.drawRect(0,0,100,20);
    sp.graphics.endFill();
    addChild(sp);
    //要執行雙擊事件,必須將其屬性設置為true
    sp.doubleClickEnabled = true;
    //創建按鈕上文字
    var label:TextField=new TextField();
    label.text="雙擊按鈕";
    label.doubleClickEnabled=true;
    sp.addChild(label);
    //創建雙擊事件處理函數
    function dbclick(event:MouseEvent):void {
          label.text="你雙擊了按鈕";
    }
    //注冊雙擊事件偵聽器
    sp.addEventListener(MouseEvent.DOUBLE_CLICK,dbclick);

完成后的效果如圖5.5所示。

圖5.5 雙擊效果圖

范例三:創建一個可以拖放的顯示對象

先創建一個圓形的顯示對象,然后把press事件偵聽器注冊給MouseEvent. MOUSE_DOWN事件,把release事件偵聽器注冊給MouseEvent.MOUSE_UP,實現在顯示對象上按下鼠標可以拖動,釋放鼠標后停止拖動效果。代碼如下所示:

    //創建圓形作為拖放對象
    var sp:Sprite=new Sprite();
    sp.graphics.beginFill(0xff0000);
    sp.graphics.drawCircle(100,100,40);
    sp.graphics.endFill();
    addChild(sp);
    //設置圓形可以接受按鈕事件
    sp.buttonMode=true;
    //創建拖動函數
    function press(evt:MouseEvent):void {
          //執行拖動
          evt.target.startDrag();
    }
    //創建停止拖動函數
    function release(evt:MouseEvent):void {
          evt.target.stopDrag();
    }
    //注冊鼠標按下事件
    sp.addEventListener(MouseEvent.MOUSE_DOWN,press);
    //注冊鼠標松開時事件
    sp.addEventListener(MouseEvent.MOUSE_UP,release);

完成后的效果如圖5.6所示。

圖5.6 拖動效果圖

范例四:自定義的鼠標樣式

創建一個自定義的鼠標形狀,然后把move事件注冊給MouseEvent.MOUSE_MOVE事件。注意,事件的發送者是舞臺stage對象而不是創建的鼠標樣式。代碼如下所示:

    var cursor:Sprite=new Sprite();
    cursor.graphics.lineStyle(1,0x00ff00,1);
    cursor.graphics.moveTo(0,0);
    cursor.graphics.lineTo(15,8);
    cursor.graphics.lineTo(9,16);
    cursor.graphics.lineTo(0,13);
    cursor.graphics.lineTo(0,0);
    addChild(cursor);
    //以上創建鼠標樣式
    function move(evt:MouseEvent):void {
          鼠標樣式跟隨
          cursor.x=evt.stageX;
          cursor.y=evt.stageY;
          evt.updateAfterEvent();
    }
    //創建move事件偵聽函數
    stage.addEventListener(MouseEvent.MOUSE_MOVE,move);//注冊鼠標事件
    // Mouse.hide()函數控制鼠標隱藏
    Mouse.hide();

完成后的效果如圖5.7所示。

圖5.7 自定義鼠標樣式效果圖

范例五:鼠標指針劃過時產生變色效果

創建一個圓形顯示對象,把makeBlue事件偵聽器注冊給MouseEvent.ROLL_OVER事件,把makeRed事件偵聽器注冊給MouseEvent.ROLL_OUT事件。實現鼠標指針滑過對象時顯示藍色,滑出對象時顯示紅色的效果。代碼如下所示:

    //創建對象實例
    var sp:Sprite=new Sprite();
    sp.graphics.beginFill(0xff0000);
    sp.graphics.drawCircle(100,100,40);
    sp.graphics.endFill();
    addChild(sp);
    // 創建與sp關聯的 ColorTransform 實例
    var colorInfo:ColorTransform = sp.transform.colorTransform;
    //創建makeBlue事件偵聽器
    function makeBlue(event:MouseEvent):void {
          // 設置 ColorTransform 對象的顏色
          colorInfo.color = 0x003399;
          // 將更改應用于顯示對象
          event.target.transform.colorTransform = colorInfo;
    }
    function makeRed(event:MouseEvent):void {
          // 設置 ColorTransform 對象的顏色
          colorInfo.color = 0xFF0000;
          // 將更改應用于顯示對象
          event.target.transform.colorTransform = colorInfo;
    }
    sp.addEventListener(MouseEvent.ROLL_OVER,makeBlue);
    sp.addEventListener(MouseEvent.ROLL_OUT,makeRed);
    //注冊事件

完成后的效果如圖5.8所示。

圖5.8 變色效果圖

上面的范例介紹了常用的鼠標操作事件,由于其他的鼠標事件不大常用,在這里不再給出范例。

5.4.2 鍵盤事件

鍵盤操作也是Flash用戶交互操作的重要事件。在ActionScript 3.0中使用KeyboardEvent類來處理鍵盤操作事件。它有兩種類型的鍵盤事件:KeyboardEvent.KEY_DOWN和KeyboardEvent.KEY_UP。

?KeyboardEvent.KEY_DOWN:定義按下鍵盤時事件。

?KeyboardEvent.KEY_UP:定義松開鍵盤時事件。

注意 在使用鍵盤事件時,要先獲得它的焦點,如果不想指定焦點,可以直接把stage作為偵聽的目標。

下面定義一個顯示對象,把keydown偵聽器注冊給KeyboardEvent.KEY_DOWN事件,把keyup偵聽器注冊給KeyboardEvent.KEY_UP事件,實現按下鍵盤時顯示對象顯示文字“你按了鍵盤”,松開鍵盤上的鍵時顯示對象顯示文字“你現在松開了按下的鍵”。代碼如下所示:

    //創建矩形對象
    var sp:Sprite=new Sprite();
    sp.graphics.beginFill(0xff0000);
    sp.graphics.drawRect(0,0,100,20);
    sp.graphics.endFill();
    addChild(sp);
    //創建顯示文本對象
    var label:TextField=new TextField();
    label.text="";
    sp.addChild(label);
    //按下鍵盤事件處理函數
    function keydown(event:KeyboardEvent):void {
          label.text="你按了鍵盤";
    }
    //松開鍵盤事件處理函數
    function keyup(event:KeyboardEvent):void {
          label.text="你現在松開了按下的鍵";
    }
    //注冊事件偵聽
    stage.addEventListener(KeyboardEvent.KEY_DOWN,keydown);
    stage.addEventListener(KeyboardEvent.KEY_UP,keyup);

注意 因為在使用時要獲得焦點,所以要先用鼠標左鍵單擊一下顯示對象,然后按下鍵盤。

完成后的效果如圖5.9所示。

圖5.9 按鍵測試效果圖

在ActionScript 2.0中,使用key類取得一些鍵的操作事件,比如Key.ENTER、Key.LEFT等,使用key.getcode()方法來獲取按下的鍵值。在ActionScript 3.0中同樣可以進行這些事件操作,不過這些屬性和方法變為Keyboard.DOWN、Keyboard.UP等,而Key.getCode變為了keyCode。keyCode會返回正在按下或釋放的鍵的鍵控代碼值。

下面的示例創建一個顯示對象,并且使用上下左右鍵控制其簡單運動。代碼如下所示:

    var box=new Sprite();
    addChild(box);
    box.graphics.beginFill(0xff0000);
    box.graphics.drawRect(0,0,40,40);
    box.graphics.endFill();
    box.x=stage.stageWidth / 2;
    box.y=stage.stageHeight / 2;
    //建立顯示對象box
    stage.addEventListener(KeyboardEvent.KEY_DOWN,keyevt);
    //在舞臺上注冊鍵盤按下事件
    //建立事件偵聽器
    function keyevt(event:KeyboardEvent):void {
          switch (event.keyCode) {                     //獲取當前鍵盤代碼
                case Keyboard.UP:                        //按下向上鍵
                      box.y-= 10;
                      break;
                case Keyboard.DOWN:                     //按下向下鍵
                      box.y+= 10;
                      break;
                case Keyboard.LEFT:                     //按下向左鍵
                      box.x-= 10;
                      break;
                case Keyboard.RIGHT:                    //按下向右鍵
                      box.x+= 10;
                      break;
                default:
                      break;
          }
    }

完成后的效果如圖5.10所示。

圖5.10 鍵盤控制顯示對象效果圖

要使用鍵盤進行操作,觸發相關事件,最好使用Keyboard類提供的預定義常量值來引用相應的keyCode屬性,而不是鍵控代碼。因為鍵和鍵控代碼之間的對應關系取決于設備和操作系統。當然也可以通過鍵控代碼來觸發事件。比如上面的示例把上、下、左、右4個鍵換為W、S、A、D4個鍵,代碼如下所示:

    var box=new Sprite();
    addChild(box);
    box.graphics.beginFill(0xff0000);
    box.graphics.drawRect(0,0,40,40);
    box.graphics.endFill();
    box.x=stage.stageWidth / 2;
    box.y=stage.stageHeight / 2;
    //建立顯示對象box
    //在舞臺上注冊鍵盤按下事件
    stage.addEventListener(KeyboardEvent.KEY_DOWN,keyevt);
    //建立事件偵聽器
    function keyevt(event:KeyboardEvent):void {
          //獲取當前鍵盤代碼
          switch (event.keyCode) {
                case 87:                  //按下W鍵
                    box.y-= 10;
                    break;
                case 83:                  //按下S鍵
                    box.y+= 10;
                    break;
                case 65:                  //按下A鍵
                    box.x-= 10;
                    break;
                case 68:                  //按下D鍵
                    box.x+= 10;
                    break;
                default:
                    break;
          }
    }

5.4.3 時間事件

在ActionScript 3.0中使用Timer類取代ActionScript之前版本中的setinterval()函數,而執行對Timer類調用的事件進行管理的是TimerEvent事件類。要注意的是,Timer類建立的事件間隔要受到SWF文件的幀頻和Flash Player的工作環境(比如計算機的內存的大小)的影響,會導致計算不準確。

Timer類有兩個事件:

?TimerEvent.TIMER:計時事件,按照設定的事件發出。

?TimerEvent.TIMER_COMPLETE:計時結束事件,當計時結束時發出。

下面的示例建立一個簡單的1分鐘倒計時效果,代碼如下所示:

    //創建一個文本框,用于顯示時間
    var label:TextField=new TextField();
    addChild(label);
    //以上建立一個文本框用于顯示倒計時時刻
    var myTimer:Timer = new Timer(1000,60);
    //1秒為間隔,觸發60次動作
    myTimer.addEventListener(TimerEvent.TIMER, timefun);
    //timefun事件偵聽器注冊給TimerEvent.TIMER事件
    myTimer.start();
    //開始計時
    var time:Number=60;
    //倒計時時間
    //顯示當前時間
    label.text=String(time);
    //創建事件偵聽器
    function timefun(the:TimerEvent):void {
          //記錄次數遞減
          time-=1;
          //顯示次數
          label.text=String(time);
    }

完成后的效果如圖5.11所示。

圖5.11 倒計時效果圖

5.4.4 幀循環ENTER_FRAME事件

幀循環ENTER_FRAME事件是ActionScript 3.0中動畫編程的核心事件。該事件能夠控制代碼跟隨Flash的幀頻播放,在每次刷新屏幕時改變顯示對象。

使用該事件時,需要把該事件代碼寫入事件偵聽函數中,然后在每次刷新屏幕時,都會調用Event. ENTER_FRAME事件,從而實現動畫效果。

下面使用該事件創建一個簡單的動畫:在屏幕中創建一個ball,每次刷新屏幕時,讓ball的x屬性增加一點,直到超出屏幕區域時返回左邊繼續,這樣就形成了連續的動畫效果。代碼如下所示:

    //創建ball對象
    var ball:Sprite=new Sprite();
    ball.graphics.beginFill(0xff0000);
    ball.graphics.drawCircle(0,0,10);
    ball.graphics.endFill();
    //加入舞臺
    addChild(ball);
    //設置初始位置
    ball.x=50;
    ball.y=200;
    //創建事件偵聽函數
    function moveball(evt:Event):void {
          //改變位置
          ball.x++;
    }
    //注冊事件
    ball.addEventListener(Event.ENTER_FRAME,moveball);

注意

在使用幀循環ENTER_FRAME事件時,由于該循環一旦被執行,就會不斷地刷新屏幕,所以如果不需要動畫,或不需要偵聽該事件時,一定要移除該偵聽。由于偵聽此類事件將消耗大量的系統資源,所以一定要及時刪除。

5.5 練習題

1. 簡述addEventListener函數的5個參數的含義,以及強引用和弱引用的區別。

2. 簡述AS 3.0的事件機制。

3. 下列關于TimerEvent和ENTER_FRAME事件描述正確的是( )。

A. Timer計時器的時間間隔是準確的,不受Flash Player運行程序時的速度影響

B. ENTER_FRAME事件以幀頻速率響應

C. Timer時間間隔單位為秒

D. Timer計時結束時,會自動刪除TimerEvent. TIMER時間

4. 如何自定義一個帶參數的事件并廣播?

5. 思考一下,鼠標事件中的MOUSE_OVER和ROLL_OVER有什么異同點。

主站蜘蛛池模板: 隆回县| 德化县| 富宁县| 十堰市| 清新县| 高淳县| 建宁县| 平阳县| 无极县| 滦南县| 盐津县| 菏泽市| 响水县| 外汇| 紫阳县| 台山市| 吴江市| 紫云| 汶上县| 久治县| 南昌市| 乐亭县| 根河市| 宜城市| 宜兰县| 淳安县| 溆浦县| 嵩明县| 霍州市| 麻城市| 龙门县| 邵东县| 政和县| 平罗县| 沧源| 葵青区| 黑河市| 利辛县| 桑植县| 会昌县| 华安县|