- ActionScript 3.0從入門到精通(視頻實(shí)戰(zhàn)版)
- 蔣國強(qiáng) 岳元亞等編著
- 169字
- 2018-12-31 19:52:49
第5章 事件的發(fā)送和處理
事件處理系統(tǒng)是交互式程序設(shè)計(jì)的重要基礎(chǔ)。利用事件處理機(jī)制,可以方便地相應(yīng)用戶輸入和系統(tǒng)事件。ActionScript 3.0的事件機(jī)制基于文檔對象模型(DOM3),是業(yè)界標(biāo)準(zhǔn)的事件處理體系結(jié)構(gòu)。使用機(jī)制不僅方便,而且符合標(biāo)準(zhǔn)。ActionScript 3.0全新的事件處理機(jī)制是ActionScript編程語言中的重大改進(jìn),對ActionScript程序設(shè)計(jì)人員來說,在使用上也更加的方便和直觀。
5.1 事件處理基礎(chǔ)
本節(jié)將介紹事件和處理的基本概念,了解常見的事件處理任務(wù)。對照ActionScript編程語言中不同版本的事件處理機(jī)制的異同,明確ActionScript 3.0中事件處理機(jī)制具有良好的性能。
5.1.1 事件和事件處理基礎(chǔ)知識
事件和事件處理是面向?qū)ο缶幊痰幕A(chǔ)。本小節(jié)將介紹事件和事件處理的基礎(chǔ)知識以及事件處理的方法和事件處理的任務(wù)。
1. 事件和事件處理基本概念
在宏觀的對象上,事件指的是當(dāng)前所發(fā)生的事情。比如人,人要張口吃飯,張口是一個動作,也就是當(dāng)前發(fā)生了一個張口事件,這個事件的結(jié)果是吃飯。編程語言中的事件,和宏觀對象的事件類似,同樣指當(dāng)前程序所能接收到的當(dāng)前所發(fā)生的事情。比如,現(xiàn)在單擊了一下鼠標(biāo),也就是發(fā)生了單擊鼠標(biāo)這一狀況,而這一狀況就被稱為發(fā)生了鼠標(biāo)單擊事件。
事件處理是指在發(fā)生了某個事件之后,需要怎么樣來應(yīng)對,下一步要做什么。還以“張口”這一事件為例,口張開了,下面將要發(fā)生的事情可能有多種,比如吃飯、呼吸等,那么需要有下一步的動作提示,才能繼續(xù)下去,所以才有了張口吃飯這一完整的動作。同樣,在發(fā)生了鼠標(biāo)單擊動作之后,需要指出下一步要做什么,是輸出一段文字,還是開始播放一段動畫,這就需要進(jìn)行事件處理,實(shí)現(xiàn)在發(fā)生事件后下一步的動作。用于處理事件的函數(shù)或方法,習(xí)慣上稱為事件偵聽器或事件偵聽函數(shù)。
張口吃飯,是因?yàn)楦杏X到了“張口”這一動作,才了解發(fā)生了這一事件。在編程的過程中,要了解當(dāng)前是不是發(fā)生了事件,發(fā)生了什么事件,需要使用事件偵聽來完成。事件偵聽的目的就是為了了解當(dāng)前有哪些事件發(fā)生,發(fā)生了什么狀況。
張口吃飯,感覺到了“張口”這一動作,而這一感覺來自于神經(jīng)系統(tǒng),是對“口”進(jìn)行神經(jīng)分析的結(jié)果。與此類似,要知道程序中的某個對象發(fā)生了某個事件,就要給這個對象加上一個控制神經(jīng),即事件偵聽,使得系統(tǒng)能夠了解事件的發(fā)生。給對象添加事件偵聽的過程,在編程語言中習(xí)慣稱為在某個對象上注冊某個事件偵聽函數(shù)。
2. ActionScript 3.0中的事件和事件處理
ActionScript編程語言支持各種類型的交互操作,能夠接受各種不同的事件。無論是響應(yīng)鼠標(biāo)單擊、敲擊鍵盤這些簡單的操作,還是接受和處理文本框中輸入的數(shù)據(jù)這樣復(fù)雜的用戶交互,與SWF文件進(jìn)行的任何類型的交互操作都可以被視為事件。即使在沒有用戶操作的情況下也有可能發(fā)生事件。比如從后臺加載完數(shù)據(jù)或者接受了一個遠(yuǎn)程的連接要求等。
在ActionScript 3.0中,每一個事件都用一個事件對象來表示。事件對象是Event(事件)類或者Event類的子類的實(shí)例。事件對象用于存儲特定的事件信息,包含操作對象的方法。比如當(dāng)Flash Player監(jiān)測到用鍵盤操作時,就會創(chuàng)建一個KeyboardEvent(鍵盤事件)事件對象實(shí)例,用于記錄該鍵盤操作事件。
創(chuàng)建事件對象后,F(xiàn)lash Player就會“調(diào)度”該事件對象,將該事件對象傳遞給作為事件目標(biāo)的對象。比如Flash Player監(jiān)聽到鍵盤輸入操作后,創(chuàng)建的事件對象就會被傳遞到對應(yīng)的事件目標(biāo)對象對事件進(jìn)行處理。
在ActionScript 3.0中,可以通過事件偵聽器來“偵聽”代碼中的事件對象。“事件偵聽器”是用戶自己編寫的用于響應(yīng)特定事件的函數(shù)或者方法。需要將事件偵聽器添加到事件目標(biāo),或者添加到作為事件對象事件流的一部分顯示對象列表,才能實(shí)現(xiàn)程序響應(yīng)事件。比如要監(jiān)聽鍵盤操作的事件對象,需要實(shí)現(xiàn)把事件偵聽器注冊到Stage對象上。
編寫事件偵聽器代碼的語法格式如下:
function事件偵聽函數(shù)(事件對象:事件類型):void{ //此處是為響應(yīng)事件而執(zhí)行的動作 } 事件目標(biāo).addEventListener(事件對象的事件名稱 事件偵聽函數(shù));
說明
此段代碼執(zhí)行兩個操作,一是定義一個函數(shù),指定為響應(yīng)事件而執(zhí)行的動作或者方法;另一個是為指定事件“注冊”該函數(shù),當(dāng)該事件發(fā)生時,執(zhí)行該函數(shù)的動作。
要創(chuàng)建自己的事件偵聽器,需要注意以下格式說明。
?事件偵聽函數(shù):指定響應(yīng)事件要執(zhí)行的動作或方法。
?事件對象:要偵聽的事件所調(diào)度的事件對象指定相應(yīng)的類名稱。
?事件目標(biāo):被偵聽的目標(biāo)對象名稱。
?事件對象的事件名稱:在事件對象類中具體的事件常量。
3. ActionScript 3.0中的事件處理任務(wù)
在ActionScript 3.0編程過程中,常見的使用事件處理的任務(wù)有:
?編寫代碼以響應(yīng)事件。
?阻止代碼響應(yīng)事件。
?處理事件對象。
?處理事件流。
?從類中調(diào)度事件。
?創(chuàng)建自定義事件類型。
5.1.2 早期 ActionScript 版本中的事件處理
ActionScript 1.0使用on()和onClipEvent()兩個事件處理函數(shù)來處理事件。具體包括:
?on()事件處理函數(shù),直接放在按鈕或者影片剪輯實(shí)例上。
?onClipEvent()處理函數(shù),直接放在影片剪輯實(shí)例上。
這種方法把代碼直接加在實(shí)例上,簡單、方便、直接,但是由于分散在各個不同的元件之上,難以管理和維護(hù)。特別是處理不是本人編寫的代碼時,查看和找尋會浪費(fèi)太多的寶貴時間。
在ActionScript 2.0中對事件處理進(jìn)行了改進(jìn),增加了一些事件處理機(jī)制,具體為:
?回調(diào)函數(shù)事件:onload、oninit、onComplete等。
?事件偵聽器:addListener()、addEventListener()。
特別是增加的事件偵聽機(jī)制,已經(jīng)實(shí)現(xiàn)了ActionScript 3.0的部分功能。但是在ActionScript 2.0中還存在著很多的不足,給開發(fā)人員造成了很大的困擾,比如下面的幾個方面。
?ActionScript 2.0中只有組件(UIComponent)類才有內(nèi)置事件,其核心類和Flash API都沒有內(nèi)置事件。
?事件偵聽器的注冊方式也有兩種:一種是addListener();一種是addEventListener()。使用起來容易造成混淆。
?ActionScript 2.0中關(guān)鍵字this的含義在各個事件處理系統(tǒng)中并不一致,造成this關(guān)鍵字指向不明確。
5.1.3 ActionScript 3.0中的事件處理
在ActionScript 3.0引入了基于文檔對象模型(DOM3)唯一的一種事件處理模式,取代了以前各版本中存在的眾多的事件處理機(jī)制。在ActionScript 3.0中只存在一種事件處理模型,雖然會對一些老版本的用戶和一些非開發(fā)者造成一定的麻煩,但更加清晰,更加標(biāo)準(zhǔn),更符合面向?qū)ο箝_發(fā)的需要。
對比ActionScript 2.0,ActionScript 3.0的事件處理體系具有以下幾個新特點(diǎn):
?在ActionScript 3.0中,只能使用addEventListener()注冊偵聽器。
?在ActionScript 3.0中,可以對屬于事件流部分的任何對象調(diào)用addEventListener()方法。
?在ActionScript 3.0中,只有函數(shù)或方法可以是事件偵聽器。
5.2 Event類
在ActionScript 3.0的事件處理系統(tǒng)中,事件對象主要有兩個作用:一是將事件信息儲存在一組屬性中,來代表具體事件;二是包含一組方法,用于操作事件對象和影響事件處理系統(tǒng)的行為。
ActionScript 3.0中,在Flash播放器的應(yīng)用程序接口中,有一個Event類,作為所有事件對象的基類,也就是說,程序中所發(fā)生的事件都必須是Event類或者其子類的實(shí)例。
5.2.1 了解Event類的屬性
Event類公開的屬性有type、cancelable、target、currentTarget、eventphase、bubles。
1. type屬性
每個事件對象都有關(guān)聯(lián)的事件類型。事件類型存儲以字符串的形式存儲在Event.type屬性中。利用事件類型,可以區(qū)分不同類型的事件。比如下面的代碼說明給clickHandler()偵聽器函數(shù)響應(yīng)傳遞給myobj的任何鼠標(biāo)單擊事件對象。
myobj.addEventListener(MouseEvent.CLICK,clickHandler);
事件類型與Event類自身關(guān)聯(lián)并由Event類常數(shù)表示,在Event類中存在二十多種事件類型常量。利用這些常數(shù)可以引用特定的事件類型,使用時要使用這些常數(shù)而不是它所代表的字符串。如果在使用時輸入了錯誤的常數(shù)名稱,編譯器會報錯。但是如果不使用常量而使用字符串,編譯時可能不會提示錯誤名稱,而可能會導(dǎo)致難以調(diào)試的意外情況。比如添加事件偵聽器時,請使用以下代碼:
myobj. addEventListener(MouseEvent.CLICK,clickHandler);
而不是ActionScript 2.0中的代碼:
myobj. addEventListener("click", clickHandler);
注意 事件的類型是區(qū)分大小寫的。
2. cancelable屬性
事件的默認(rèn)行為是否可以被阻止由布爾值表示,并存儲在Event.cancelable屬性中。此屬性是一個布爾值,默認(rèn)為false。這個屬性一般是和preventDefault()方法結(jié)合在一起使用的。
3. target屬性
target屬性用于存儲對事件目標(biāo)的引用。下面先生成一個顯示(sprite)對象sp,然后給其注冊一個鼠標(biāo)單擊事件,單擊之后,使用target屬性實(shí)現(xiàn)對顯示對象的引用,并使sp的位置發(fā)生改變。代碼如下所示:
//定義一個變量,使用繪圖對象創(chuàng)建一個圓 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); //把圓加入舞臺中 addChild(sp); //創(chuàng)建事件偵聽函數(shù) function TestTar(event:MouseEvent):void { //通過獲取目標(biāo),跳轉(zhuǎn)對象位置 event.target.x=300; event.target.y=100; } //注冊事件偵聽 sp.addEventListener(MouseEvent.CLICK,TestTar);
完成后的效果如圖5.1所示。

圖5.1 事件目標(biāo)效果圖
4. 其他屬性
currentTarget、eventphase和bubbles這3個屬性都和ActionScript 3.0的事件流機(jī)制有關(guān),在平時用到的不多。
要注意的是,實(shí)例屬性全部是只讀屬性[read-only]。這些屬性是使用getter方法實(shí)現(xiàn)的,并不是真正的實(shí)例屬性。
Event類還有26個靜態(tài)字符串常量,定義了26種事件類型。其中包括:“ADDED”表示對象被添加到顯示列表時發(fā)送事件;“REMOVED”表示對象從顯示列表被移除時發(fā)送事件;“UNLOAD”表示對象被卸載時發(fā)送事件。
5.2.2 了解Event類的方法
Event類的方法有7種:clone()、toString()、stopPropogation()、stopImmediatePropogation()、preventDefault()、isDefaultPrevented()和formatToString()。這些方法的用途如下:
?Event.clone()方法用于賦值Event子類實(shí)例,返回Event對象原始實(shí)例的副本。當(dāng)需要自定義Event子類時,就必須要繼承Event.clone()方法,用于賦值自定義類的屬性。另外還要加上新的屬性,否則在偵聽器重寫調(diào)用時,這些屬性的值會出現(xiàn)錯誤。
?Event.toString()屬性返回一個包含Event對象的所有屬性的字符串。如果要自定義事件類,那么重寫toString()方法時,可以使用formatToString()這個方法在返回的字符串中加入新的事件實(shí)例屬性。
?Event.stopPropogation()方法可阻止事件對象移動到下一個節(jié)點(diǎn),但只有在允許執(zhí)行當(dāng)前節(jié)點(diǎn)上的任何其他事件偵聽器之后才起作用。
?Event.stopImmediatePropogation()方法也阻止事件對象移動到下一個節(jié)點(diǎn),但不允許執(zhí)行當(dāng)前節(jié)點(diǎn)上的任何其他事件偵聽器。
?Event.preventDefault()、Event.isDefaultPrevented()和Event.cancelable屬性結(jié)合使用,用于取消事件的默認(rèn)行為的發(fā)生。
5.2.3 Event類的子類
對于很多事件來說,使用Event類的一組屬性就已經(jīng)足夠了。但是,Event類中的屬性無法捕獲其他事件具有的獨(dú)特的特性,比如鼠標(biāo)的單擊事件、鍵盤的輸入事件等。ActionScript 3.0的應(yīng)用程序接口特意為這些具有顯式特征的事件準(zhǔn)備了Event類的幾個子類。這些子類主要包括:
?鼠標(biāo)類:MouseEvent。
?鍵盤類:KeyBoardEvent。
?時間類:TimerEvent。
?文本類:TextEvent。
每個子類定義了對于該種事件類別來說唯一的附加屬性和事件類型。比如,與鼠標(biāo)輸入相關(guān)的事件具有若干獨(dú)特的特性,無法被Event類中定義的屬性捕獲。MouseEvent類則添加了10個屬性,擴(kuò)展了Event類。這10個屬性包含諸如鼠標(biāo)事件的位置和在鼠標(biāo)事件過程中是否按下了特定鍵等信息。
Event子類還增加了代表與子類關(guān)聯(lián)的事件類型的常量。例如,MouseEvent類定義幾種鼠標(biāo)事件類型的內(nèi)容,包括click、doubleClick、mouseDown和mouseUp事件類型。
當(dāng)然,有時可能需要在事件對象中加入額外的屬性或方法時,這就需要自定義事件類。
關(guān)于這些子類的用法,后面的章節(jié)會逐步講述。
5.3 事件偵聽器
事件偵聽器也就是以前版本中的事件處理函數(shù),是事件的處理者,負(fù)責(zé)接收事件攜帶的信息,并在接收到該事件之后執(zhí)行事件處理函數(shù)體內(nèi)的代碼。
添加事件偵聽的過程有兩步:第一步是創(chuàng)建一個事件偵聽函數(shù);第二步是使用addEventListener()方法在事件目標(biāo)或者任何顯示對象上注冊偵聽器函數(shù)。
5.3.1 創(chuàng)建事件偵聽器
事件偵聽器必須是函數(shù)類型,可以是一個自定義的函數(shù),也可以是實(shí)例的一個方法。創(chuàng)建偵聽器的語法格式如下:
function 偵聽器名稱(evt:事件類型):void{...}
語法格式說明如下:
?偵聽器名稱:要定義的事件偵聽器的名稱,命名需符合變量命名規(guī)則。
?evt:事件偵聽器參數(shù),為必需。
?事件類型:Event類實(shí)例或其子類的實(shí)例。
?void:返回值必須為空,不可省略。
下面代碼創(chuàng)建一個顯示紅色圓形的簡單SWF文件,并使用名為Test()的偵聽器函數(shù)偵聽紅色圓形上的鼠標(biāo)單擊事件。代碼如下所示:
//定義一個變量,使用繪圖對象創(chuàng)建一個圓 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); //把圓加入舞臺中 addChild(sp); //創(chuàng)建事件偵聽函數(shù) function Test(event:MouseEvent):void { trace("事件偵聽函數(shù)建立成功!") } //注冊事件偵聽器 sp.addEventListener(MouseEvent.CLICK,Test);
說明
在顯示的紅色圓形上單擊鼠標(biāo),輸出為“事件偵聽函數(shù)建立成功!”,說明事件偵聽器建立成功。
完成后的效果如圖5.2所示。

圖5.2 注冊事件偵聽測試
ActionScript 3.0主要是面向?qū)ο蟮木幊潭O(shè)計(jì),所以事件偵聽函數(shù)同樣可以為類方法。把代碼寫成文檔類可以實(shí)現(xiàn)相同的效果。代碼如下所示:
//創(chuàng)建包 package Lzxt { //導(dǎo)入包Sprite import flash.display.Sprite; //創(chuàng)建類 public class Test extends Sprite { //構(gòu)造函數(shù) public function Test() { //創(chuàng)建對象 var sp:Csp = new Csp(); //加入對象 addChild(sp); } } } //包外類,用于創(chuàng)建對象 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); } //創(chuàng)建事件偵聽函數(shù) private function testclick(event:MouseEvent):void { trace("類方法實(shí)現(xiàn)事件處理函數(shù)"); } }
說明
在顯示的紅色圓形上單擊鼠標(biāo),輸出為“類方法實(shí)現(xiàn)事件處理函數(shù)”,說明事件偵聽器建立成功。
完成后的效果如圖5.3所示。

圖5.3 類方法實(shí)現(xiàn)事件偵聽效果
5.3.2 管理事件偵聽器
在ActionScript 3.0中使用IEventDispatcher接口的方法來管理偵聽器函數(shù),主要用于注冊、檢查和刪除事件偵聽器。
1. 注冊事件偵聽器
addEventListener()函數(shù)用來注冊事件偵聽函數(shù)。注冊偵聽器的語法格式如下:
事件發(fā)送者.addEventListener(事件類型,偵聽器);
語法格式說明如下:
?事件發(fā)送者:其必須為EventDispatcher類或子類的實(shí)例。
?事件類型:Event類實(shí)例或其子類的實(shí)例。
?偵聽器:事件執(zhí)行時的偵聽器函數(shù),注意,此數(shù)的函數(shù)不要函數(shù)名后的括號。
下面代碼示例把Test()函數(shù)注冊為sp對象的偵聽器,接收鼠標(biāo)單擊事件:
sp.addEventListener(MouseEvent.CLICK,Test);
注意下面的注冊語句是錯誤的:
sp.addEventListener(MouseEvent.CLICK,Test());
2. 刪除事件偵聽器
removeEventListener()函數(shù)用來刪除事件偵聽器函數(shù)。刪除偵聽器的語法格式如下:
事件發(fā)送者.removeEventListener(事件類型,偵聽器);
事件發(fā)送者、事件類型和偵聽器的要求與注冊事件偵聽器的要求相同,不再贅述。
將不再使用的所有偵聽器刪除可以節(jié)約系統(tǒng)資源,提高程序效率。下面代碼創(chuàng)建一個顯示紅色圓形的簡單SWF文件。名為Test()的偵聽器函數(shù)偵聽紅色圓形上的鼠標(biāo)單擊事件,當(dāng)單擊之后,刪除事件偵聽器。代碼如下所示:
//定義一個變量,使用繪圖對象創(chuàng)建一個圓 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); //把圓加入舞臺中 addChild(sp); //創(chuàng)建事件偵聽函數(shù) function Test(event:MouseEvent):void { trace("事件偵聽函數(shù)建立成功!") //移除事件偵聽函數(shù) sp.removeEventListener(MouseEvent.CLICK,Test); } //注冊事件偵聽函數(shù) sp.addEventListener(MouseEvent.CLICK,Test);
說明
在顯示的紅色圓形上單擊鼠標(biāo),輸出為“事件偵聽函數(shù)建立成功!”,說明事件偵聽器建立成功,再次單擊,沒有任何輸出,說明事件偵聽器已經(jīng)被刪除。
3. 檢查事件偵聽器
HasEventListener()方法和willTragger()方法,都可以用來檢測當(dāng)前的事件發(fā)送者注冊了何種事件類型的偵聽器。
檢查事件偵聽器語法格式如下:
事件發(fā)送者.hasEventListener(事件類型);
繼續(xù)使用上面的效果,在鼠標(biāo)單擊紅色圓形之前檢查一次事件偵聽器,并在單擊之后再檢查一次事件偵聽器。代碼如下所示:
//定義一個變量,使用繪圖對象創(chuàng)建一個圓 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); //把圓加入舞臺中 addChild(sp); //創(chuàng)建事件偵聽函數(shù) function Test(event:MouseEvent):void { trace("事件偵聽函數(shù)建立成功!"); //移除事件偵聽 sp.removeEventListener(MouseEvent.CLICK,Test); trace(sp.hasEventListener(MouseEvent.CLICK)); } //注冊事件偵聽 sp.addEventListener(MouseEvent.CLICK,Test); trace(sp.hasEventListener(MouseEvent.CLICK));
代碼執(zhí)行后的輸出結(jié)果如下所示:
true
事件偵聽函數(shù)建立成功!
false
說明
從輸出結(jié)果可以看出,在刪除事件偵聽器之前,該事件存在,輸出為true,當(dāng)刪除之后,輸出為false。
willTrigger()方法同樣也可以檢查事件偵聽器。willTrigger()不但會檢查該顯示對象上的偵聽器,還會檢查該顯示列表對象在事件流所有階段中的所有父級上的偵聽器。
下面的代碼先建立一個紅色的圓形,然后在紅色圓形中建立一個黃色的小圓形,名為Test()的偵聽器函數(shù)偵聽紅色圓形上的鼠標(biāo)單擊事件,最后檢查黃色圓形上的事件偵聽器。代碼如下所示:
//定義一個變量,使用繪圖對象創(chuàng)建一個圓 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); //把圓加入舞臺中 addChild(sp); //創(chuàng)建另一個對象 var spp:Sprite=new Sprite(); spp.graphics.beginFill(0xffff00); spp.graphics.drawCircle(100,100,20); spp.graphics.endFill(); sp.addChild(spp); //創(chuàng)建事件偵聽函數(shù) function Test(event:MouseEvent):void { trace("事件偵聽函數(shù)建立成功!"); } //注冊事件偵聽函數(shù) sp.addEventListener(MouseEvent.CLICK,Test); trace(spp.hasEventListener(MouseEvent.CLICK)); trace(spp.willTrigger(MouseEvent.CLICK)); /* 輸出為: false true */
說明
輸出的結(jié)果可以說明hasEventListener()方法只能檢測指定的顯示對象上的事件偵聽器,而willTrigger()方法還可以檢查該顯示對象父級上的顯示對象。
5.4 事件處理類型
ActionScript 3.0使用單一事件模式來管理事件,所有的事件都位于flash.events包內(nèi),其中構(gòu)建了二十多個Event類的子類,用來管理相關(guān)的事件類型。本節(jié)介紹常用的鼠標(biāo)事件(MouseEvent)類型、鍵盤事件(KeyboardEvent)類型和時間事件(TimerEvent)類型和幀循環(huán)(ENTER_FRAME)事件。
5.4.1 鼠標(biāo)事件
在ActionScript 3.0之前的語言版本中,常常使用on(press)或者onClipEvent(mousedown)等方法來處理鼠標(biāo)事件。而在ActionScript 3.0中,統(tǒng)一使用MouseEvent類來管理鼠標(biāo)事件。在使用過程中,無論是按鈕還是影片事件,統(tǒng)一使用addEventListener注冊鼠標(biāo)事件。此外,若在類中定義鼠標(biāo)事件,則需要先引入(import)flash.events.MouseEvent類。
MouseEvent類定義了10種常見的鼠標(biāo)事件,具體如下:
?CLICK:定義鼠標(biāo)單擊事件。
?DOUBLE_CLICK:定義鼠標(biāo)雙擊事件。
?MOUSE_DOWN:定義鼠標(biāo)按下事件。
?MOUSE_MOVE:定義鼠標(biāo)移動事件。
?MOUSE_OUT:定義鼠標(biāo)移出事件。
?MOUSE_OVER:定義鼠標(biāo)移過事件。
?MOUSE_UP:定義鼠標(biāo)提起事件。
?MOUSE_WHEEL:定義鼠標(biāo)滾軸滾動觸發(fā)事件。
?ROLL_OUT:定義鼠標(biāo)滑入事件。
?ROLL_OVER:定義鼠標(biāo)滑出事件。
下面通過幾個范例來說明這些鼠標(biāo)事件的使用方法,并解決從ActionScript 2.0到ActionScript 3.0過程中一些原有實(shí)現(xiàn)方法的轉(zhuǎn)換。
范例一:給顯示對象添加鼠標(biāo)單擊事件
下面先建立一個簡單按鈕,把名為click的事件偵聽器注冊到按鈕上,執(zhí)行鼠標(biāo)單擊事件,按鈕上的文字提示“你單擊了按鈕”。代碼如下所示:
//創(chuàng)建矩形作為按鈕背景 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawRect(0,0,100,20); sp.graphics.endFill(); addChild(sp); //創(chuàng)建按鈕上的文本 var label:TextField=new TextField(); label.text="單擊按鈕"; sp.addChild(label); //創(chuàng)建單擊事件處理函數(shù) function click(event:MouseEvent):void { //單擊后改變的文字內(nèi)容 label.text="你單擊了按鈕"; } //注冊鼠標(biāo)單擊事件 sp.addEventListener(MouseEvent.CLICK,click);
完成后的效果如圖5.4所示。

圖5.4 單擊效果圖
范例二:給顯示對象添加鼠標(biāo)雙擊事件
鼠標(biāo)雙擊事件和單擊事件的使用方法相同,但是,系統(tǒng)默認(rèn)鼠標(biāo)雙擊事件并沒有打開,需要把鼠標(biāo)雙擊屬性(double-ClickEnabled)打開,否則即使執(zhí)行了雙擊操作,按鈕也不會響應(yīng)操作。
下面同樣建立一個簡單按鈕,把名為dbclick的事件偵聽器注冊到按鈕上,雙擊按鈕,按鈕上的文字變?yōu)椤澳汶p擊了按鈕”。代碼如下所示:
//創(chuàng)建按鈕背景 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawRect(0,0,100,20); sp.graphics.endFill(); addChild(sp); //要執(zhí)行雙擊事件,必須將其屬性設(shè)置為true sp.doubleClickEnabled = true; //創(chuàng)建按鈕上文字 var label:TextField=new TextField(); label.text="雙擊按鈕"; label.doubleClickEnabled=true; sp.addChild(label); //創(chuàng)建雙擊事件處理函數(shù) function dbclick(event:MouseEvent):void { label.text="你雙擊了按鈕"; } //注冊雙擊事件偵聽器 sp.addEventListener(MouseEvent.DOUBLE_CLICK,dbclick);
完成后的效果如圖5.5所示。

圖5.5 雙擊效果圖
范例三:創(chuàng)建一個可以拖放的顯示對象
先創(chuàng)建一個圓形的顯示對象,然后把press事件偵聽器注冊給MouseEvent. MOUSE_DOWN事件,把release事件偵聽器注冊給MouseEvent.MOUSE_UP,實(shí)現(xiàn)在顯示對象上按下鼠標(biāo)可以拖動,釋放鼠標(biāo)后停止拖動效果。代碼如下所示:
//創(chuàng)建圓形作為拖放對象 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); addChild(sp); //設(shè)置圓形可以接受按鈕事件 sp.buttonMode=true; //創(chuàng)建拖動函數(shù) function press(evt:MouseEvent):void { //執(zhí)行拖動 evt.target.startDrag(); } //創(chuàng)建停止拖動函數(shù) function release(evt:MouseEvent):void { evt.target.stopDrag(); } //注冊鼠標(biāo)按下事件 sp.addEventListener(MouseEvent.MOUSE_DOWN,press); //注冊鼠標(biāo)松開時事件 sp.addEventListener(MouseEvent.MOUSE_UP,release);
完成后的效果如圖5.6所示。

圖5.6 拖動效果圖
范例四:自定義的鼠標(biāo)樣式
創(chuàng)建一個自定義的鼠標(biāo)形狀,然后把move事件注冊給MouseEvent.MOUSE_MOVE事件。注意,事件的發(fā)送者是舞臺stage對象而不是創(chuàng)建的鼠標(biāo)樣式。代碼如下所示:
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); //以上創(chuàng)建鼠標(biāo)樣式 function move(evt:MouseEvent):void { 鼠標(biāo)樣式跟隨 cursor.x=evt.stageX; cursor.y=evt.stageY; evt.updateAfterEvent(); } //創(chuàng)建move事件偵聽函數(shù) stage.addEventListener(MouseEvent.MOUSE_MOVE,move);//注冊鼠標(biāo)事件 // Mouse.hide()函數(shù)控制鼠標(biāo)隱藏 Mouse.hide();
完成后的效果如圖5.7所示。

圖5.7 自定義鼠標(biāo)樣式效果圖
范例五:鼠標(biāo)指針劃過時產(chǎn)生變色效果
創(chuàng)建一個圓形顯示對象,把makeBlue事件偵聽器注冊給MouseEvent.ROLL_OVER事件,把makeRed事件偵聽器注冊給MouseEvent.ROLL_OUT事件。實(shí)現(xiàn)鼠標(biāo)指針滑過對象時顯示藍(lán)色,滑出對象時顯示紅色的效果。代碼如下所示:
//創(chuàng)建對象實(shí)例 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawCircle(100,100,40); sp.graphics.endFill(); addChild(sp); // 創(chuàng)建與sp關(guān)聯(lián)的 ColorTransform 實(shí)例 var colorInfo:ColorTransform = sp.transform.colorTransform; //創(chuàng)建makeBlue事件偵聽器 function makeBlue(event:MouseEvent):void { // 設(shè)置 ColorTransform 對象的顏色 colorInfo.color = 0x003399; // 將更改應(yīng)用于顯示對象 event.target.transform.colorTransform = colorInfo; } function makeRed(event:MouseEvent):void { // 設(shè)置 ColorTransform 對象的顏色 colorInfo.color = 0xFF0000; // 將更改應(yīng)用于顯示對象 event.target.transform.colorTransform = colorInfo; } sp.addEventListener(MouseEvent.ROLL_OVER,makeBlue); sp.addEventListener(MouseEvent.ROLL_OUT,makeRed); //注冊事件
完成后的效果如圖5.8所示。

圖5.8 變色效果圖
上面的范例介紹了常用的鼠標(biāo)操作事件,由于其他的鼠標(biāo)事件不大常用,在這里不再給出范例。
5.4.2 鍵盤事件
鍵盤操作也是Flash用戶交互操作的重要事件。在ActionScript 3.0中使用KeyboardEvent類來處理鍵盤操作事件。它有兩種類型的鍵盤事件:KeyboardEvent.KEY_DOWN和KeyboardEvent.KEY_UP。
?KeyboardEvent.KEY_DOWN:定義按下鍵盤時事件。
?KeyboardEvent.KEY_UP:定義松開鍵盤時事件。
注意 在使用鍵盤事件時,要先獲得它的焦點(diǎn),如果不想指定焦點(diǎn),可以直接把stage作為偵聽的目標(biāo)。
下面定義一個顯示對象,把keydown偵聽器注冊給KeyboardEvent.KEY_DOWN事件,把keyup偵聽器注冊給KeyboardEvent.KEY_UP事件,實(shí)現(xiàn)按下鍵盤時顯示對象顯示文字“你按了鍵盤”,松開鍵盤上的鍵時顯示對象顯示文字“你現(xiàn)在松開了按下的鍵”。代碼如下所示:
//創(chuàng)建矩形對象 var sp:Sprite=new Sprite(); sp.graphics.beginFill(0xff0000); sp.graphics.drawRect(0,0,100,20); sp.graphics.endFill(); addChild(sp); //創(chuàng)建顯示文本對象 var label:TextField=new TextField(); label.text=""; sp.addChild(label); //按下鍵盤事件處理函數(shù) function keydown(event:KeyboardEvent):void { label.text="你按了鍵盤"; } //松開鍵盤事件處理函數(shù) function keyup(event:KeyboardEvent):void { label.text="你現(xiàn)在松開了按下的鍵"; } //注冊事件偵聽 stage.addEventListener(KeyboardEvent.KEY_DOWN,keydown); stage.addEventListener(KeyboardEvent.KEY_UP,keyup);
注意 因?yàn)樵谑褂脮r要獲得焦點(diǎn),所以要先用鼠標(biāo)左鍵單擊一下顯示對象,然后按下鍵盤。
完成后的效果如圖5.9所示。

圖5.9 按鍵測試效果圖
在ActionScript 2.0中,使用key類取得一些鍵的操作事件,比如Key.ENTER、Key.LEFT等,使用key.getcode()方法來獲取按下的鍵值。在ActionScript 3.0中同樣可以進(jìn)行這些事件操作,不過這些屬性和方法變?yōu)镵eyboard.DOWN、Keyboard.UP等,而Key.getCode變?yōu)榱薻eyCode。keyCode會返回正在按下或釋放的鍵的鍵控代碼值。
下面的示例創(chuàng)建一個顯示對象,并且使用上下左右鍵控制其簡單運(yùn)動。代碼如下所示:
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) { //獲取當(dāng)前鍵盤代碼 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 鍵盤控制顯示對象效果圖
要使用鍵盤進(jìn)行操作,觸發(fā)相關(guān)事件,最好使用Keyboard類提供的預(yù)定義常量值來引用相應(yīng)的keyCode屬性,而不是鍵控代碼。因?yàn)殒I和鍵控代碼之間的對應(yīng)關(guān)系取決于設(shè)備和操作系統(tǒng)。當(dāng)然也可以通過鍵控代碼來觸發(fā)事件。比如上面的示例把上、下、左、右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 { //獲取當(dāng)前鍵盤代碼 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()函數(shù),而執(zhí)行對Timer類調(diào)用的事件進(jìn)行管理的是TimerEvent事件類。要注意的是,Timer類建立的事件間隔要受到SWF文件的幀頻和Flash Player的工作環(huán)境(比如計(jì)算機(jī)的內(nèi)存的大小)的影響,會導(dǎo)致計(jì)算不準(zhǔn)確。
Timer類有兩個事件:
?TimerEvent.TIMER:計(jì)時事件,按照設(shè)定的事件發(fā)出。
?TimerEvent.TIMER_COMPLETE:計(jì)時結(jié)束事件,當(dāng)計(jì)時結(jié)束時發(fā)出。
下面的示例建立一個簡單的1分鐘倒計(jì)時效果,代碼如下所示:
//創(chuàng)建一個文本框,用于顯示時間 var label:TextField=new TextField(); addChild(label); //以上建立一個文本框用于顯示倒計(jì)時時刻 var myTimer:Timer = new Timer(1000,60); //以1秒為間隔,觸發(fā)60次動作 myTimer.addEventListener(TimerEvent.TIMER, timefun); //把timefun事件偵聽器注冊給TimerEvent.TIMER事件 myTimer.start(); //開始計(jì)時 var time:Number=60; //倒計(jì)時時間 //顯示當(dāng)前時間 label.text=String(time); //創(chuàng)建事件偵聽器 function timefun(the:TimerEvent):void { //記錄次數(shù)遞減 time-=1; //顯示次數(shù) label.text=String(time); }
完成后的效果如圖5.11所示。

圖5.11 倒計(jì)時效果圖
5.4.4 幀循環(huán)ENTER_FRAME事件
幀循環(huán)ENTER_FRAME事件是ActionScript 3.0中動畫編程的核心事件。該事件能夠控制代碼跟隨Flash的幀頻播放,在每次刷新屏幕時改變顯示對象。
使用該事件時,需要把該事件代碼寫入事件偵聽函數(shù)中,然后在每次刷新屏幕時,都會調(diào)用Event. ENTER_FRAME事件,從而實(shí)現(xiàn)動畫效果。
下面使用該事件創(chuàng)建一個簡單的動畫:在屏幕中創(chuàng)建一個ball,每次刷新屏幕時,讓ball的x屬性增加一點(diǎn),直到超出屏幕區(qū)域時返回左邊繼續(xù),這樣就形成了連續(xù)的動畫效果。代碼如下所示:
//創(chuàng)建ball對象 var ball:Sprite=new Sprite(); ball.graphics.beginFill(0xff0000); ball.graphics.drawCircle(0,0,10); ball.graphics.endFill(); //加入舞臺 addChild(ball); //設(shè)置初始位置 ball.x=50; ball.y=200; //創(chuàng)建事件偵聽函數(shù) function moveball(evt:Event):void { //改變位置 ball.x++; } //注冊事件 ball.addEventListener(Event.ENTER_FRAME,moveball);
注意
在使用幀循環(huán)ENTER_FRAME事件時,由于該循環(huán)一旦被執(zhí)行,就會不斷地刷新屏幕,所以如果不需要動畫,或不需要偵聽該事件時,一定要移除該偵聽。由于偵聽此類事件將消耗大量的系統(tǒng)資源,所以一定要及時刪除。
5.5 練習(xí)題
1. 簡述addEventListener函數(shù)的5個參數(shù)的含義,以及強(qiáng)引用和弱引用的區(qū)別。
2. 簡述AS 3.0的事件機(jī)制。
3. 下列關(guān)于TimerEvent和ENTER_FRAME事件描述正確的是( )。
A. Timer計(jì)時器的時間間隔是準(zhǔn)確的,不受Flash Player運(yùn)行程序時的速度影響
B. ENTER_FRAME事件以幀頻速率響應(yīng)
C. Timer時間間隔單位為秒
D. Timer計(jì)時結(jié)束時,會自動刪除TimerEvent. TIMER時間
4. 如何自定義一個帶參數(shù)的事件并廣播?
5. 思考一下,鼠標(biāo)事件中的MOUSE_OVER和ROLL_OVER有什么異同點(diǎn)。
- Cocos2d Cross-Platform Game Development Cookbook(Second Edition)
- Node.js 10實(shí)戰(zhàn)
- Ext JS Data-driven Application Design
- Java Web開發(fā)之道
- 體驗(yàn)設(shè)計(jì)原理:行為、情感和細(xì)節(jié)
- Mastering matplotlib
- 表哥的Access入門:以Excel視角快速學(xué)習(xí)數(shù)據(jù)庫開發(fā)(第2版)
- Mastering Backbone.js
- Unity 3D/2D移動開發(fā)實(shí)戰(zhàn)教程
- 編寫高質(zhì)量代碼:改善Objective-C程序的61個建議
- Tableau Dashboard Cookbook
- 軟件測試技術(shù)
- MongoDB Administrator’s Guide
- Mastering Machine Learning with scikit-learn
- Scala編程(第4版)