本章將介紹變量和常量、變量的數(shù)據(jù)類型、運(yùn)算符和表達(dá)式、路徑等一些基本知識(shí),在此基礎(chǔ)上,認(rèn)識(shí) Flash 中的坐標(biāo)、角度和影片剪輯的屬性。利用這些知識(shí),可以制作一些簡單的效果如直線運(yùn)動(dòng)等。
2.4 路徑
在一個(gè)學(xué)校中有校長、老師、學(xué)生,老師中又有語文老師、數(shù)學(xué)老師等。校長和老師之間有信息交流,老師和學(xué)生也有信息交流等。
一個(gè) Flash 影片好比是一個(gè)學(xué)校,可以由多個(gè)影片剪輯組成,這些影片剪輯中,可以有自己的時(shí)間軸,有自己的變量等。影片剪輯之間是怎樣進(jìn)行交換信息的呢?這與 Flash 中的路徑有關(guān)。
2.4.1 絕對(duì)路徑
如果校長要找學(xué)生,可以這樣進(jìn)行,校長先找到下一級(jí)的老師,老師再找下一級(jí)的學(xué)生,表示如下:
校長 . 老師 . 學(xué)生
主場(chǎng)景( _root )好比是校長,主場(chǎng)景中的影片剪輯( mcA )好比是老師,影片剪輯( mcA )下的影片剪輯( mc1 )好比是學(xué)生,如果要在主場(chǎng)景中訪問影片剪輯 mc1 ,用如下方式:
_root.mcA.mc1;
在 Flash 影片中從起點(diǎn)(如從主場(chǎng)景開始)調(diào)用變量或影片剪輯,這樣的語法稱為絕對(duì)路徑。它簡單、容易理解,但移植性差。
范例 2-13 :使用絕對(duì)路徑
( 1 )打開 Flash MX 2004 ,新建一個(gè) Flash 文檔。
: 當(dāng)建立一個(gè)新文件時(shí),出現(xiàn)在面前的場(chǎng)景即主場(chǎng)景,用 _root 表示。
( 2 )在主場(chǎng)景中建立一個(gè)實(shí)例名為“ mcA ”的影片剪輯實(shí)例,雙擊 mcA 進(jìn)入元件的編輯場(chǎng)景,建立一個(gè)實(shí)例名為“ mc1 ”的影片剪輯實(shí)例。在【時(shí)間軸】的上方可以顯示出影片剪輯實(shí)例的順序。如圖 2.18 所示。
圖 2.18 影片剪輯實(shí)例的順序
( 3 )返回主場(chǎng)景,新建一層,單擊此層的第 1 幀,打開【動(dòng)作】面板,輸入下列代碼:
trace(_root.mcA._width);
// 輸出影片剪輯實(shí)例 mcA 的寬度
trace(_root.mcA.mc1._width);
// 輸出影片剪輯 mc1 的寬度
( 4 )測(cè)試影片,觀看【輸出】面板中輸出的數(shù)據(jù)。
( 5 )返回主場(chǎng)景,把主場(chǎng)景第 1 幀中的代碼中改為:
trace(mcA._width);
trace(mcA.mc1._width);
測(cè)試影片,結(jié)果是一樣的。
從測(cè)試結(jié)果可看出,在主場(chǎng)景中使用絕對(duì)路徑,可省略 _root 。
( 6 )返回主場(chǎng)景,把第 1 幀中的代碼加上注釋,在主場(chǎng)景中加入一個(gè)按鈕,單擊按鈕,打開【動(dòng)作】面板,輸入下列代碼:
on (release) {
trace(_root.mcA._width);
trace(_root.mcA.mc1._width);
}
測(cè)試影片,單擊按鈕,觀看測(cè)試結(jié)果。
( 7 )返回主場(chǎng)景中,把按鈕中的代碼改為:
on (release) {
trace(mcA._width);
trace(mcA.mc1._width);
}
測(cè)試影片,單擊按鈕,觀看測(cè)試結(jié)果,測(cè)試結(jié)果不變。
從測(cè)試結(jié)果可看出,主場(chǎng)景中的按鈕上的代碼可以看成是在主場(chǎng)景中的時(shí)間軸上執(zhí)行,所以可以不加 _root 。
( 8 )返回主場(chǎng)景,把按鈕中的代碼加上注釋,雙擊場(chǎng)景中的影片剪輯實(shí)例,在第 1 幀上加上下列代碼:
trace(_root.mcA._width);
trace(_root.mcA.mc1._width);
測(cè)試影片,結(jié)果與前面相同。
( 9 )關(guān)閉測(cè)試窗口,把第 1 幀上的代碼改為:
trace(mcA._width);
trace(mcA.mc1._width);
測(cè)試影片,結(jié)果錯(cuò)誤。
從測(cè)試結(jié)果可看出,影片剪輯有自己的時(shí)間軸,它的代碼是在自己的時(shí)間軸上執(zhí)行,所以必須加路徑 _root
Flash 文件可以由多個(gè)影片組成,一個(gè)影片可從外部動(dòng)態(tài)的導(dǎo)入到另一個(gè)影片的影片剪輯中,比如,影片“ 1.swf ”被導(dǎo)入到影片“ main.swf ”中的影片剪輯實(shí)例 mc 中,如果在影片“ 1.swf ”中的程序中有 _root ,導(dǎo)入到 mc 后,不再是主場(chǎng)景,所以路徑改變,這時(shí)“ 1.swf ”的中的代碼就不能正確的執(zhí)行,這時(shí),就要使用相對(duì)路徑來解決這個(gè)問題。
相對(duì)路徑是以自己所處的起點(diǎn)去訪問其它的變量或影片剪輯。如在范例 2-13 中,以 mc1 為起點(diǎn)訪問上一級(jí)的影片剪輯 mcA 就屬于相對(duì)路徑,這里的上一級(jí)用 _patent 表示。因?yàn)?mcA 是 mc1 的上一級(jí),在 mc1 的時(shí)間軸上加上:
_parent._x ;
意思是訪問 mc1 的上一級(jí) mcA 的 x 坐標(biāo),轉(zhuǎn)換為絕對(duì)路徑即:
_root.mcA._x;
使用相對(duì)路徑有兩層意思,一是以自己為起點(diǎn)向上訪問,需要用 _parent 。二是以自己為起點(diǎn)向下訪問,只需用點(diǎn)運(yùn)算符。
范例 2-14 :使用相對(duì)路徑訪問變量
( 1 )打開 Flash MX 2004 ,新建一個(gè) Flash 文檔。
( 2 )建立如圖 2.20 所示影片剪輯實(shí)例及其結(jié)構(gòu),圖 2.20 中的名稱代表它們的實(shí)例名。
圖 2.20 影片剪輯的關(guān)系
( 3 )單擊主場(chǎng)景的第 1 幀,打開【動(dòng)作】面板,輸入下列代碼:
var root_var = "_root";
// 在主場(chǎng)景中定義一個(gè)字符串變量,代表主場(chǎng)景
( 4 )在四個(gè)影片剪輯實(shí)例的時(shí)間軸的第 1 幀上分別定義一個(gè)變量,如下所示:
在 mcB 中:
var mcB_var = "mcB";
在 mc2 中:
var mc2_var = "mc2";
在 mcA 中:
var mcA_var = "mcA";
在 mc1 中:
var mc1_var = "mc1";
( 5 )在 mcB 的時(shí)間軸上的第 1 幀上輸入下列代碼:
trace(_parent.root_var);
( 6 )測(cè)試影片,輸出 _root 。
在這個(gè)范例中, _root 是 mcA 的上一級(jí),即 _root 是 mcA 的父級(jí),要在 mcA 的時(shí)間軸上訪問 _root 中的變量 root_var ,只需向上訪問一級(jí),表示如下:
_parent.root_var;
而 mcA 又是 mc1 的父級(jí),要在 mc1 的時(shí)間軸上訪問 _root 中的變量 root_var ,需向上訪問兩級(jí),表示如下:
_parent._parent.root_var;
mcB 是 _root 的下一級(jí),即 mcB 是 _root 的子級(jí)。要在 _root 的時(shí)間軸中訪問 mcB 的變量 mcB_var ,只需用點(diǎn)運(yùn)算符,向下訪問一級(jí),表示如下:
mcB._mcB_var;
同樣的,要在 mcB 的時(shí)間軸上訪問 mc2 中的變量,表示如下:
mc2._mc2_var;
要在 _root 的時(shí)間軸上訪問 mc2 中的變量,要向下訪問二級(jí),表示如下:
mcB.mc2._mc2_var;
要在 mc2 的時(shí)間軸中訪問 mc1 中的變量 mc1_var ,先向上訪問二級(jí),再向下訪問二級(jí),表示如下:
_parent._parent.mcA.mc1.mc1_var;
源文件見“ 2-14.fla ”(文件路徑:配套光盤 \ 源文件 \part2 \2-14.fla )。
試一試: 在本例的基礎(chǔ)上,做如下修改:
( 1 )在 mcA 中訪問 mc2 中的變量。
( 2 )在 mc2 中訪問 mcA 中的變量。
分別用 trace() 語句輸出。
注意: 在定義主場(chǎng)景中按鈕的動(dòng)作腳本時(shí),訪問主場(chǎng)景中的變量不用加路徑。
通過【動(dòng)作】面板的【插入目標(biāo)路徑】按鈕可把實(shí)例的路徑自動(dòng)添加到【動(dòng)作】面板中,這給編程帶來了很多方便。
打開源文件“ 2-14.fla ”,單擊第 1 幀,按 F9 打開【動(dòng)作】面板,單擊【動(dòng)作】面板上的【插入目標(biāo)路徑】按鈕 ,彈出【插入目標(biāo)路徑】對(duì)話框,如圖 2.21 所示。
圖 2.21 【插入目標(biāo)路徑】對(duì)話框
利用【插入目標(biāo)路徑】對(duì)話框可添加實(shí)例的相對(duì)路徑和絕對(duì)路徑。單擊【插入目標(biāo)路徑】對(duì)話框中【絕對(duì)】單選按鈕,再單擊要插入目標(biāo)路徑的實(shí)例名,即可顯示出相關(guān)實(shí)例的絕對(duì)路徑,單擊【確定】按鈕可把路徑添加到動(dòng)作面板中。如圖 2.22 所示。
圖 2.22 實(shí)例的絕對(duì)路徑
雙擊主場(chǎng)景中的實(shí)例 mcB ,單擊時(shí)間軸的第 1 幀,打開【動(dòng)作】面板上的【插入目標(biāo)路徑】對(duì)話框, 單擊【相對(duì)】單選按鈕,再單擊要插入目標(biāo)路徑的實(shí)例名,可顯示出相關(guān)實(shí)例的相對(duì)路徑。
另外,要獲取相對(duì)路徑還可用上一節(jié)的方法:先獲得絕對(duì)路徑,理清楚各個(gè)影片剪輯實(shí)例的層次關(guān)系,再?zèng)Q定向上還是向下訪問。
2.4.3 動(dòng)態(tài)路徑
影片剪輯一般通過手工創(chuàng)建,通過【屬性】面板可以設(shè)定影片剪輯實(shí)例的實(shí)例名,通過實(shí)例名和路徑就可以訪問不同層次的影片剪輯實(shí)例。但有些影片剪輯的實(shí)例是通過程序來創(chuàng)建的,例如通過復(fù)制函數(shù)可以復(fù)制出若干個(gè)新的電影剪輯實(shí)例,它們的實(shí)例名也是在程序中指定的。要訪問這些復(fù)制出來的影片剪輯實(shí)例,最好的方法是用動(dòng)態(tài)路徑。
動(dòng)態(tài)路徑是利用數(shù)組運(yùn)算符來實(shí)現(xiàn)的,在范例 2-14 中可以使用絕對(duì)路徑訪問 mcA :
_root.mcA
如果用動(dòng)態(tài)路徑可以這樣表示:
_root[“mc”+”A”]
注意: 動(dòng)態(tài)路徑使用數(shù)組運(yùn)算符“ [ ] ”實(shí)現(xiàn),路徑和實(shí)例名間沒有點(diǎn)運(yùn)算符 。
使用動(dòng)態(tài)路徑的好處是可以批量實(shí)現(xiàn)路徑。假如主場(chǎng)景中有影片剪輯實(shí)例 mc1 、 mc2 、 … 、 mc100 ,假如用絕對(duì)路徑,要寫 100 行程序,用動(dòng)態(tài)路徑就非常方便,因?yàn)檫@些實(shí)例名有一定的規(guī)律,開頭兩個(gè)字母是一樣是,都是 mc ,后面的數(shù)字可用一個(gè)變量 n 來表示,因?yàn)樽兞渴强梢宰兓模硎救缦拢?
_root[“mc”+n]
Flash 中的關(guān)鍵字 this 代表自己,如果不用 _root ,可用 this 來指定,如:
this[“mc”+n]
使用 this 的前提是不使用其它路徑,就是指當(dāng)前路徑,這里指的是主場(chǎng)景。
使用動(dòng)態(tài)路徑時(shí)也可以用相對(duì)路徑,如:
_parent[“mc”+n]
如果有多重路徑,要訪問主場(chǎng)景下的 mcA 下的 mc1 到 mc100 ,可以這樣表示:
_root.mcA[“mc”+n]
范例 2-15 :使用動(dòng)態(tài)路徑批量更改影片剪輯的屬性
( 1 )打開 Flash MX 2004 ,新建一個(gè) Flash 文檔。
( 2 )在主場(chǎng)景的【圖層 1 】上建立五個(gè)影片剪輯,實(shí)例名分別為 mc1 、 mc2 、 mc3 、 mc4 、 mc5 。
( 3 )新建一層,在此層第 1 幀上輸入下列代碼:
var n = 1;
// 定義變量 n ,初始值為 1
( 4 )在第 2 幀插入空白關(guān)鍵幀,輸入下列代碼:
_root["mc"+n]._visible = false;
// 設(shè)置影片剪輯實(shí)例為不可見
( 5 )在第 3 幀插入空白關(guān)鍵幀,輸入下列代碼:
n += 1;
// 變量 n 加 1
gotoAndPlay(2);
// 跳到第 2 幀并播放
( 6 )測(cè)試影片,可以看到全部的影片剪輯實(shí)例都變化不可見。
源文件見“ 2-15.fla ”(文件路徑:配套光盤 \part2\ 源文件 \2-15.fla )。
分析 : 此范例中,在第 1 幀中定義一個(gè)初始值為 1 的變量 n ,當(dāng)運(yùn)行到第 2 幀時(shí),因?yàn)?n=1 , _root["mc"+n]._visible = false 的作用是相當(dāng)于 _root.mc1._visible=false ,所以 mc1 變?yōu)椴豢梢?。運(yùn)行第 3 幀, n 加 1 ,變?yōu)?2 ,然后跳到第 2 幀,使 mc2 變?yōu)椴豢梢?。由于?2 和 3 幀不斷循環(huán), n 不斷加 1 ,使場(chǎng)景上影片剪輯實(shí)例一個(gè)個(gè)變?yōu)椴豢梢姟?
試一試: :把第 2 幀上代碼改為:
this["mc"+n]._visible = false;
測(cè)試影片看看效果。
動(dòng)態(tài)路徑在實(shí)際編程中的運(yùn)用非常廣泛,它大大提高了程序的編寫效率,有關(guān)動(dòng)態(tài)路徑的更多應(yīng)用將在后面的章節(jié)中講解。
PII 應(yīng)用程序開發(fā)
翻譯:zjs35
zjs35.5dblog.com
這部分內(nèi)容將教你怎樣用ActionScript 2.0構(gòu)建完整的應(yīng)用程序,你將學(xué)會(huì)架起和建立一個(gè)OO對(duì)象的最好實(shí)踐,并學(xué)會(huì)UI組件和MC怎樣適合一個(gè)有好結(jié)構(gòu)的flash應(yīng)用程序,你還將學(xué)會(huì)怎樣和其它開發(fā)者共享代碼和使用其它人開發(fā)的代碼庫。這此都將幫助你建立一個(gè)可升級(jí)的、擴(kuò)展的、穩(wěn)定的應(yīng)用程序。
第11章 一個(gè)純OOP的應(yīng)用程序框架
Flash is notoriously open-ended,If there are several of ways to skin a cat, there are even more ways to build a Flash application.(大致意思是flash建立應(yīng)用程序的方法太多了)flash的彈性能讓開發(fā)者混淆,特別是它們建立第一個(gè)應(yīng)用程序時(shí)。通過提供一個(gè)清晰的怎樣構(gòu)建一個(gè)OOP的應(yīng)用程序的例子,達(dá)到解決這種混淆的目標(biāo)。這里介紹的這個(gè)例子決不是創(chuàng)建flash應(yīng)用程序的唯一方法,但它對(duì)確是合理的、可復(fù)用的能為任何OOP工程打好基礎(chǔ)的方法。我們先在抽象層次上考慮這個(gè)例子,此時(shí)并沒有涉及任何特殊的應(yīng)用。,我們的框架能夠應(yīng)用到從一個(gè)email應(yīng)用程序到一個(gè)計(jì)算機(jī)游戲的任何東西。在下一章,我們將把我們的普通框架應(yīng)用到一個(gè)真實(shí)的案例里――貨幣轉(zhuǎn)換應(yīng)用程序。
本章描述的應(yīng)用程序的框架源自Java思想,更確切的說,是一個(gè)微軟的VB風(fēng)格。那也就是說,這個(gè)應(yīng)用程序?qū)⑹且粋€(gè)純粹的OOP應(yīng)用程序,所有的東西都在類里面,而fla文件只是用來加載類和提供組件聯(lián)接。并不是每個(gè)flash應(yīng)用程序都是純粹OOP的。Flash也充分支持drag-and-drop(拖放)的可視的開發(fā)??梢曢_發(fā)的操作包括在創(chuàng)作時(shí)通過面板手工的把組件放在場(chǎng)景中、設(shè)置組件的屬性和數(shù)據(jù)綁定,這些操作超出這本書的范圍。(下面的部分內(nèi)容教你怎樣使用幫助和google查看信息,還有源文件下載。skip)
11.1 基本的目錄結(jié)構(gòu)
在我們開始創(chuàng)作之前,先建立應(yīng)用程序的目錄結(jié)構(gòu)。
(步驟略,另和我說不會(huì),哈哈)
創(chuàng)建目錄結(jié)構(gòu)如下,隨便放在硬盤的哪個(gè)位置:
AppName/deploy/source
在我們的例子中,我們有一些外部的素材如文本,聲音、圖片等,如果這些素材很多,們應(yīng)該建立一個(gè)AppName/assets目錄來存放這些素材。
11.2 flash文檔文件
每個(gè)flash應(yīng)用程序至少包含一個(gè)fla文件,fla文件是用來導(dǎo)出影片(swf文件)的源文件,影片實(shí)際上是在播放器中展示內(nèi)容的。許多應(yīng)用程序都含有多個(gè)在運(yùn)行時(shí)單個(gè)加載的swf。例如,在一個(gè)游戲中,一個(gè)swf可能代表某一級(jí)別的游戲,在一個(gè)站點(diǎn)中,一個(gè)swf可能代表如“聯(lián)系我們”這部分內(nèi)容。在一個(gè)含有多個(gè)swf的應(yīng)用中,某個(gè)swf只是一個(gè)一個(gè)用來顯示進(jìn)度條的容器等等(moock可真會(huì)寫)。
我們的基本的應(yīng)用程序只包含一個(gè)swf文件,因此,只需一個(gè)fla文件。然而,我們的應(yīng)用程序框架不排除其它swf的使用,這些swf可能是站點(diǎn)的某部分,一個(gè)表單或測(cè)驗(yàn)的某個(gè)場(chǎng)景,一個(gè)游戲的不同級(jí)別部分。
下面創(chuàng)建我們的應(yīng)用程序的主要fla文件:
建立一個(gè)flash文檔文件,存放在AppName/source目錄中,文件名為AppName.fla。
下面讓我們來創(chuàng)建應(yīng)用程序的類文件。
11.3 類
由于我們建立的是一個(gè)純粹OOP的應(yīng)用程序,因此所有的內(nèi)容都在類文件中創(chuàng)建。在flash中,大部分應(yīng)用程序都是包括可視的用戶界面圖形,因此,一個(gè)典型的OOP應(yīng)用程序中,由類文件創(chuàng)建和管理UI組件。但在我們的例子里,只有兩個(gè)類?,F(xiàn)在,把我們的焦點(diǎn)只放在框架的構(gòu)建上,所以既不用類創(chuàng)建視覺元素,也不用類完成特定的實(shí)際任務(wù)。為了強(qiáng)調(diào)框架的一般性和自然性,我們把兩個(gè)類命名為A和B。我們來看怎樣創(chuàng)建組件和管理基于現(xiàn)在的框架的結(jié)構(gòu)用戶界面。
一個(gè)OOP應(yīng)用程序可能有許多個(gè)類,但只有一個(gè)用來開始應(yīng)用程序,在我們的例子中,類A用來開始應(yīng)用程序,類A有一個(gè)通常命名為main()的方法,按照習(xí)慣,這個(gè)方法包含應(yīng)用程序的開始代碼。在真實(shí)的應(yīng)用程序中,類A將被含一個(gè)用來完成開始任務(wù)的main()方法的類代替。例如,在一個(gè)測(cè)驗(yàn)應(yīng)用程序中,主要的類可能是Quiz,main( )方法用來初始化測(cè)驗(yàn)和顯示第一個(gè)問題。在一個(gè)聊天應(yīng)用程序中,首要的類可能是ChatClient,main()方法可能用來連接服務(wù)器。在上面的兩個(gè)例子中,應(yīng)用程序的接下去的部分是從main()方法執(zhí)行之后開始的。例如,第1個(gè)問題答案的出現(xiàn)可能使第2個(gè)問題出現(xiàn),或者服務(wù)器的成功連接使聊天界面出現(xiàn)。
基于對(duì)我們的應(yīng)用程序的框架的考慮,我們認(rèn)為類A的開始任務(wù)是創(chuàng)建類B的一個(gè)實(shí)例。
注:類方法main()的使用是嚴(yán)格按照java方法的,在flash中,main()的使用是可以選擇的。在java中,由于語言的需要,main()方法是必須的,main()方法會(huì)被自動(dòng)調(diào)用。但在flash中,你必須手工調(diào)用main()方法,時(shí)間軸的第1幀要跟在應(yīng)用程序預(yù)載之后。
我們將把類保存在包c(diǎn)om.somedomain中,在你的應(yīng)用程序中,你應(yīng)讓包c(diǎn)om.somedomain與你的站點(diǎn)的蜮名相匹配。例如,我的站點(diǎn)的蜮名是moock.org,我創(chuàng)建的所有類都在包moock.org之內(nèi)。
創(chuàng)建包:
1、 在AppName/source目錄下建立一個(gè)名為com的文件夾
2、在AppName/source/com目錄下,建立一個(gè)名為somedomain的子文件夾
創(chuàng)建類A:
1、建立一個(gè)動(dòng)作腳本文件
2、輸入下列代碼:
import com.somedomain.B;
class A {
private static var bInstance:B;
public function A() {
// 在這個(gè)例子中,類A的構(gòu)造函數(shù)不使用
}
public static function main():Void {
trace("Starting application.");
bInstance = new B( );
}
}
3、保存到AppName/source/com/somedomain,文件名A.as
創(chuàng)建類B:
class com.somedomain.B {
public function B() {
trace("類B的一個(gè)實(shí)例被創(chuàng)建");
}
}
在我們的框架中,請(qǐng)注意,我們把類保存在AppName/source目錄中,這是合理的,但這不是一定要這樣做,理論上講,類能保存在任何地方,只要這個(gè)目錄能被添加到全局或文檔類路徑,些目錄中的類就能在時(shí)間軸上或其它類中使用。
11.4 時(shí)間軸
現(xiàn)在我們已經(jīng)創(chuàng)建兩個(gè)類和一個(gè)flash文檔,讓我們看看AppName.fla怎樣加載類和調(diào)用類方法A.main()來開始我們的應(yīng)用程序。
在我們的應(yīng)用程序框架中,將使用AppName.fla來創(chuàng)建基本的應(yīng)用程序狀態(tài):loading 和 main,每種狀態(tài)都是在相應(yīng)的有標(biāo)簽的幀通過暫停播放頭來實(shí)現(xiàn),在幀標(biāo)簽loading中,當(dāng)類加載時(shí)顯示一個(gè)加載信息,在幀標(biāo)簽main中,調(diào)用A.main( )方法開始應(yīng)用程序。
注:在應(yīng)用程序中使用幀標(biāo)簽作為程序的狀態(tài)是一個(gè)通常的做法(不管是OOP還是沒有OOP),雖然這種用法是非常普遍的,但對(duì)于熟悉其它語言的程序員來說,這種做法很不適應(yīng),也很不熟悉。為了解決這個(gè)情況,flash引入了基于屏幕的表單應(yīng)用程序,關(guān)于屏幕類更多的信息請(qǐng)看….
要加載類A和B,需要這些步驟:
1、在幀中為類指定輸出幀
2、在AppName.fla的時(shí)間軸上添加幀標(biāo)簽loading 和 main
3、當(dāng)影片加載時(shí),添加代碼顯示加載信息
這些步驟的詳細(xì)方法將在下面列出來:
1、打開AppName.fla文件
2、選擇文件――發(fā)布設(shè)置
3、在發(fā)布設(shè)置對(duì)話框中,選擇flash標(biāo)簽,單擊設(shè)置按鈕,在彈出的對(duì)話框中,在導(dǎo)出用于類的幀的文本框中輸入10,這個(gè)10是任意的,但這個(gè)指定的幀須在顯示加載信息的代碼之后(也就是預(yù)載之后)。
4、單擊兩次確定按鈕完成操作
在AppName.fla的時(shí)間軸上添加幀標(biāo)簽,
1、修改圖層1的名稱為scripts,我們將把代碼放在這一層中,做為一個(gè)好的習(xí)慣,你應(yīng)該把所有的代碼放在scripts圖層中,在時(shí)間軸中,這個(gè)圖層位于最上層,它只包含代碼,不含mc或其它內(nèi)容,一些開發(fā)者用actions代替scripts,但目的是一樣的。
2、選擇scripts圖層的第15幀
3、播放一關(guān)鍵幀
4、插入一個(gè)新的圖層,
5、把新圖層命名為labels.
6、在labels圖層的第4和15幀,插入一關(guān)鍵幀,就像scipts圖層只包含代碼一樣,labels圖層專門用于設(shè)置幀標(biāo)簽,用幀標(biāo)簽代替幀數(shù)目指定某個(gè)幀是非常便利的、友好的。
7、在labels圖層的第4幀,加入標(biāo)簽loading
8、在labels圖層的第15幀,加入標(biāo)簽main
添加代碼用來顯示加載信息:
1、在scripts圖層的第5幀插入一關(guān)鍵幀
2、在scripts圖層的第5幀,輸入下列代碼:
if (_framesloaded == _totalframes) {
gotoAndStop("main");
} else {
gotoAndPlay("loading");
}
3、在scripts圖層的第1幀,輸入下列代碼:
this.createTextField("loadmsg_txt", 0, 200, 200, 0, 0);
loadmsg_txt.autoSize = true;
loadmsg_txt.text = "Loading...Please wait.";
4、在scripts圖層的第15幀,輸入下列代碼:
loadmsg_txt.removeTextField( );
我們現(xiàn)在已經(jīng)提供了基本的時(shí)間軸結(jié)構(gòu),接下去調(diào)用A.main()方法來開始應(yīng)用程序,我們將在幀標(biāo)簽main處來完成它,下面是此幀的代碼:
loadmsg_txt.removeTextField();
import com.somedomain.A;
A.main();
在理論上講,這是我們對(duì)AppName.fla的最后一次改動(dòng),除非我們要增加組件、聲音或傳統(tǒng)的圖形。應(yīng)用程序的所有代碼都在通過A.main()方法直接引用或間接引用類中,在AppName.fla中將不放置任何代碼。
我們的應(yīng)用程序完成了,現(xiàn)在我們測(cè)試應(yīng)用程序是否能正常運(yùn)行,要進(jìn)行測(cè)試,我們要輸出一個(gè)swf文件,然后在flash播放器中運(yùn)行。
11.5 輸出flash影片
指定一個(gè)目錄用來輸出AppName.swf文件:
1、在AppName.fla打開的狀態(tài)下,選擇文件――發(fā)布設(shè)置――格式
2、在文件下面,輸入:../deploy/AppName.swf.
3、單擊確定按鈕
4、為了在測(cè)試模式下測(cè)試我們的應(yīng)用程序,選擇控制――測(cè)試影片,實(shí)際上測(cè)試影片就是在AppName/deploy目錄創(chuàng)建一個(gè)swf文件和立即把它加載進(jìn)播放器的調(diào)試器。
對(duì)于我們的應(yīng)用程序,我們將輸出flash7格式,如果你想別人使用其它版本的播放器,你也可以輸入其它版本的格式
如果你的應(yīng)用程序能正常運(yùn)行,在輸出面板中將看到下列信息:
Starting application.
An instance of class B was constructed.
如果上述的信息沒有出現(xiàn),可嘗試比較你的源文件和本書的源文件
發(fā)布html文件:略
在所有支持的flash播放器版本、所有的網(wǎng)頁瀏覽器和所有的平臺(tái)中測(cè)試是不個(gè)好想法,如果你等到所有項(xiàng)目完成之后才在各種各樣的瀏覽器中測(cè)試,你可能會(huì)發(fā)現(xiàn)嚴(yán)重的問題,如果它們被盡早發(fā)現(xiàn),修復(fù)起來也是容易的。
11.6 flash中的項(xiàng)目
為了在大的應(yīng)用程序中管理文件,flash支持項(xiàng)目的概念,一個(gè)項(xiàng)目是一群有關(guān)系的文件,這些文件能通過項(xiàng)目面板進(jìn)行管理,一個(gè)項(xiàng)目面板像資源管理器,有以下的特征:
l 綜合了控制應(yīng)用程序的源文件
l 容易訪問關(guān)聯(lián)的文件
l 即使在編輯類文件時(shí),也可以發(fā)布應(yīng)用程序
這個(gè)內(nèi)容超出了本書的范圍,更多內(nèi)容請(qǐng)看幫助
11.7 小結(jié)
雖然這章感覺是非常概念化的,但它展示了非常重要的OOP開發(fā)的基礎(chǔ),也是這本書下面的許多例子的基礎(chǔ)。
譯自:Essential ActionScript 2.0 第二部分第11章
貨幣轉(zhuǎn)換應(yīng)用程序這個(gè)例子只進(jìn)行簡單的貨幣轉(zhuǎn)換,下圖顯示了這個(gè)程序所需的界面,包括一些UI組件實(shí)例(Button, ComboBox, Label, TextArea, and TextInput)。在這個(gè)應(yīng)用程序中,用戶必須輸入一個(gè)加拿大元的數(shù)目,然后從下拉列表中選擇貨幣類型,再單擊轉(zhuǎn)換按鈕,就能在文本框中顯示出轉(zhuǎn)換后的等量的貨幣數(shù)值。
圖12-1 應(yīng)用程序的界面
和第11章的使用的結(jié)構(gòu)對(duì)應(yīng),我們將把元素放在下面的目錄下,在創(chuàng)建目錄時(shí)要注意, deploy和source都是CurrencyConverte文件夾的子目錄,org/moock/tools是source文件夾的子目錄。
CurrencyConverter/
deploy/
source/
org/
moock/
tools/
這個(gè)應(yīng)用程序的主要部分是名為CurrencyConverter.fla的flash文檔文件,為了創(chuàng)建這個(gè)文件,我們把AppName.fla(在第11章創(chuàng)建的)復(fù)制到CurrencyConverter/source目錄中,然后把AppName.fla重命名為CurrencyConverter.fla。這樣CurrencyConverter.fla就具有了基本的所需結(jié)構(gòu),包括類的預(yù)載等(詳見第11章)。
這個(gè)應(yīng)用程序只有一個(gè)CurrencyConverter類,這個(gè)類位于CurrencyConverter/source/org/moock/tools中,而導(dǎo)出的CurrencyConverter.swf位于CurrencyConverter/deploy目錄中。
現(xiàn)在讓我們開始貨幣轉(zhuǎn)換應(yīng)用程序的每個(gè)細(xì)節(jié)。
12.2 準(zhǔn)備flash文檔文件
CurrencyConverter類將在運(yùn)行時(shí)實(shí)例化應(yīng)用程序所需的組件。雖然我們是在運(yùn)行時(shí)創(chuàng)建組件的實(shí)例,flash仍然要求把組件添加到CurrencyConverter.fla的庫中。不幸的是,flash不允許直接從組件面板中把組件拖到庫中。如果我們要在庫中添加一個(gè)組件,必須在場(chǎng)景中先創(chuàng)建組件的實(shí)例。雖然組件實(shí)例可以直接留在了fla文件的場(chǎng)景中,但這種開發(fā)模式不是我們現(xiàn)在的重點(diǎn),因此必須把場(chǎng)景中的組件實(shí)例刪除。不管哪種方法,flash都把組件加入了庫中(這是我們最初的目的)。
12.1.1 添加組件到flash文檔文件
步驟:拖入組件,然后刪除
如果我們?cè)谝粋€(gè)全新的fla文件中創(chuàng)作,組件就已準(zhǔn)備好被實(shí)例化了,然而,回憶我們?cè)诘?1章的fla文件中的創(chuàng)作,當(dāng)類被加載時(shí),在第10幀導(dǎo)出類和顯示加載信息。由于這個(gè)預(yù)載結(jié)構(gòu),如果我們想使用組件,這些組件將不能工作,因此我們要把組件整合到預(yù)載結(jié)構(gòu)里。
注:當(dāng)一個(gè)類在fla文件中的第1幀以后被導(dǎo)出時(shí),組件將不能工作,除非組件是在類導(dǎo)出幀的后面加載。
為了在第10幀以后加載組件,必須設(shè)定組件在第1幀不能導(dǎo)出,然后我們?cè)诘?0幀后放置每個(gè)組件的虛的實(shí)例,這些虛的實(shí)例是不能被使用的,它只是用來加載組件。
下面的步驟就是阻止Button實(shí)例在第1幀導(dǎo)出,其它組件的設(shè)置方法與些類似:
1、在庫中選中Button組件
2、單擊庫面板的右上角,從下拉菜單中選擇“鏈接”
3、在鏈接屬性對(duì)話框中的鏈接一欄,不選中“第1幀導(dǎo)出”多選按鈕
4、單擊確定按鈕
當(dāng)一個(gè)組件的“第1幀導(dǎo)出”多選按鈕沒選中時(shí),除非一個(gè)組件實(shí)例被放在了時(shí)間軸上,否則組件將不被影片編譯。組件將在放置它的實(shí)例的幀上導(dǎo)出,但是在組件導(dǎo)出之前,組件的初始化過程仍需要一個(gè)可用的類。因此,在CurrencyConverter.fla文件中,我們將在第12幀放置每個(gè)組件的實(shí)例。為了存放虛的組件實(shí)例,要?jiǎng)?chuàng)建新的圖層和關(guān)鍵幀:
建立一個(gè)名為load components的圖層,在第12和13幀插入關(guān)鍵幀,這兩幀的作用是不讓虛的實(shí)例顯示在應(yīng)用程序中,虛的實(shí)例只是用來加載,CurrencyConverter類是真正的組件實(shí)例的創(chuàng)造者。
當(dāng)組件加載幀制作好后,把虛的實(shí)例放在時(shí)間軸上:
1、選中第12幀
2、從庫中拖入每個(gè)組件到場(chǎng)景中
3、就像在圖12-2中顯示的一樣,隨便的使用組件檢查器為組件實(shí)例增加虛的表示不被使用的文字。
圖12-2 應(yīng)用程序的時(shí)間軸和場(chǎng)景
12.2.2 開始應(yīng)用程序
在第11章,我們知道了通過調(diào)用第一個(gè)類的mian()方法來開始應(yīng)用程序,在這里,也將通過調(diào)用urrencyConverter類的mian()方法來開始應(yīng)用程序,當(dāng)類和組件被加載后,main方法將在CurrencyConverter.fla時(shí)間的scripts圖層的第15幀被調(diào)用。下面是調(diào)用的代碼:
import org.moock.tools.CurrencyConverter;
CurrencyConverter.main(this, 0, 150, 100);
注意:通過使用完整的、有效的包路徑,import關(guān)鍵字允許我們通過CurrencyConverter類的類名訪問CurrencyConverter。上述的代碼的意思是,類的main( )方法要指定四個(gè)參數(shù):擁有貨幣轉(zhuǎn)換的mc、深度、水平位置和垂直位置。
fla文件現(xiàn)在已經(jīng)準(zhǔn)備好了,我們將把注意力轉(zhuǎn)移到類的創(chuàng)建和管理應(yīng)用程序本身。
12.3 CurrencyConverter類
CurrencyConverter類要實(shí)現(xiàn)3個(gè)任務(wù):
l 提供一個(gè)方法開始應(yīng)用程序
l 創(chuàng)建應(yīng)用程序界面
l 響應(yīng)用戶的輸入等操作
在調(diào)試完成上述任務(wù)的類代碼之前,你應(yīng)該快速瀏覽例12-1中代碼清單?,F(xiàn)在,你沒有必要太仔細(xì)的閱讀代碼,在這章的后面將會(huì)對(duì)這些代碼做詳細(xì)的介紹。
例12-1: CurrencyConverter類
12.3.1 導(dǎo)入組件包
CurrencyConverter類需要用到各種各樣的組件類,我們需要的組件類位于包mx.controls中。在CurrencyConverter類中,我們要通過組件類的類名來使用這些組件,如as mx.controls.Button 或 mx.controls.ComboBox,這個(gè)明顯是很麻煩的,因此,在定義CurrencyConverter類之前,我們導(dǎo)入整個(gè)包:
import mx.controls.*;
一旦這個(gè)包被導(dǎo)入,我們就不用使用完整的類名,可以直接使用如Button等組件類,要特別注意的是,并不是所有的組件都是位于mx.controls包中,如一些容器組件如Window 和 ScrollPane是位于包mx.containers中。要查看組件的包,可參考幫助。
12.3.2 CurrencyConverter類屬性
CurrencyConverter類定義了兩種一般的屬性:類屬性指定了貨幣的兌換率,實(shí)例屬性保存了應(yīng)用程序所需的組件:
代碼略
出于對(duì)本例子的考慮,在類屬性中的兌換率是不變的,在真實(shí)的貨幣轉(zhuǎn)換應(yīng)用程序中,它們更可能是通過動(dòng)態(tài)的、保存在服務(wù)器中的數(shù)據(jù)代替。
要注意,不是所有UI組件都保存在實(shí)例屬性中,如果一些組件不需要被再次使用,就不用保存在實(shí)例屬性中。當(dāng)創(chuàng)建一個(gè)組件時(shí),我們保存對(duì)組件實(shí)例的一個(gè)引用只是設(shè)想類里的另一個(gè)方法稍后要使用它。
12.3.3 main()方法
這個(gè)應(yīng)用程序開始的方法就是main()方法:
public static function main(target:MovieClip, depth:Number, x:Number, y:Number):Void {
var converter:CurrencyConverter = new CurrencyConverter(target, depth, x, y);
}
main()方法是一個(gè)類方法,因?yàn)樗菫橥暾膽?yīng)用程序調(diào)用,并且沒有和一個(gè)特別的類關(guān)聯(lián)。Main()方法創(chuàng)建了CurrencyConverter類的第一個(gè)實(shí)例,并把實(shí)例保存在一個(gè)本地變量converter中。實(shí)際上, CurrencyConverter類創(chuàng)建了一個(gè)自己的實(shí)例,這個(gè)做法是合理的、普遍的。
就像我們先前看到的,main()方法從幀標(biāo)簽main處被調(diào)用,當(dāng)main()方法消失時(shí),指向?qū)嵗淖兞縞onverter也將不存在,它會(huì)自動(dòng)被刪除。然而,應(yīng)用程序?qū)⒗^續(xù)運(yùn)行,創(chuàng)建的mc和組件實(shí)例即使沒有被保存在變量或?qū)傩灾?,也繼續(xù)留在場(chǎng)景上,直到它們被移除。
正如我們后面看到的,通過main()方法產(chǎn)生的實(shí)例在buildConverter( )方法中能繼續(xù)存在,通過buildConverter( )方法創(chuàng)建的mc和組件實(shí)例也保持著一個(gè)對(duì)實(shí)例的指向,沒有這個(gè)指向,應(yīng)用程序?qū)⒉粫?huì)響應(yīng)組件事件。
12.3.4 類的構(gòu)造函數(shù)
這個(gè)類的構(gòu)造函數(shù)是簡單的,它只是調(diào)用了buildConverter( )方法來創(chuàng)建應(yīng)用程序的用戶界面。
public function CurrencyConverter(target:MovieClip, depth:Number, x:Number, y:Number) {
buildConverter(target, depth, x, y);
}
這個(gè)構(gòu)造函數(shù)傳遞參數(shù)給程序的另一個(gè)部分,在這個(gè)例子中,是傳遞給通過參數(shù)創(chuàng)建用戶界面的buildConverter( )方法。
12.3.5 創(chuàng)建用戶界面
正如剛才學(xué)的,這個(gè)應(yīng)用程序的界面是通過buildConverter( )方法創(chuàng)建的,為了創(chuàng)建用戶界面,buildConverter( )方法實(shí)例化了UI組件,定義了事件處理器來指示界面的行為。
你已經(jīng)在前面的例12-1中看了buildConverter( )方法,現(xiàn)在讓我們一行一行來看。
buildConverter( )方法的第一行對(duì)一些程序員可能是陌生的,它定義一個(gè)局部變量thisConverter,來保存對(duì)當(dāng)前對(duì)象的一個(gè)引用。
var thisConverter:CurrencyConverter = this;
保存一個(gè)當(dāng)前對(duì)象到一個(gè)局部變量,只是允許當(dāng)前對(duì)象能被嵌套的函數(shù)調(diào)用,當(dāng)這些嵌套的函數(shù)存在時(shí),當(dāng)前對(duì)象也是存在的。不久我們將看到,事件處理器能在嵌套的函數(shù)中執(zhí)行。它們使用變量thisConverter來訪問CurrencyConverter類的實(shí)例,關(guān)于這個(gè)技術(shù)的更多信息,在第14章還會(huì)提到。
12.3.5.1 界面容器
現(xiàn)在我們繼續(xù)創(chuàng)建界面元素,首先,要?jiǎng)?chuàng)建一個(gè)影片剪輯容器用來放置所有的組件,我們將給這個(gè)容器命名為converter,放在指定深度的target影片剪輯里面,回憶在main()中的參數(shù)target和depth,這兩個(gè)參數(shù)先傳遞給構(gòu)造函數(shù),再傳遞給buildConverter( )方法:
converter_mc = target.createEmptyMovieClip("converter", depth);
把所有的組件放在一個(gè)影片剪輯里,把這些組件做為一個(gè)群體來操作將變得非常容易。例如,要移動(dòng)所有的組件,只需移動(dòng)影片剪輯的坐標(biāo):
converter_mc._x = x;
converter_mc._y = y;
這時(shí)的x和y是提供給main()方法的參數(shù)。
注意:我們的影片剪輯容器保存在實(shí)例屬性converter_mc中,保存影片剪輯到屬性保證了它能被外部的buildConverter( )訪問,或者說是出于重新設(shè)置或刪除它的目的。在我們的這個(gè)案例里,我們沒有重置或刪除這個(gè)容器。因此,從理論上講,我們能把它保存在代替屬性的局部變量里。然而,我們把它保存在了實(shí)例屬性converter_mc里,只是為了在將來能把類增加功能。
13.5.5.2 標(biāo)簽(Label)組件
現(xiàn)在我們的容器已經(jīng)準(zhǔn)備好了,我們就能把組件放在它的里面,通過使用Label組件,先給應(yīng)用程序一個(gè)標(biāo)題,Label組件常來顯示一個(gè)單行的文本:
下面的代碼是在converter_mc里創(chuàng)建一個(gè)名為title的Label組件實(shí)例,title的深度為0:
var title:Label = converter_mc.createClassObject(Label, "title", 0);
在我們這個(gè)應(yīng)用程序里,所有的組件都是用UIObject 類的 createClassObject( )方法來創(chuàng)建,這個(gè)方法有三個(gè)參數(shù),分別用來指定:
l 要?jiǎng)?chuàng)建的組件類
l 組件的實(shí)例名
l 在父影片剪輯或組件里的深度
createClassObject( )方法返回了一個(gè)新組件實(shí)例的指向,在這個(gè)案例的title實(shí)例里,我們把這個(gè)指向保存在了變量title里,之所以使用局部變量title,是因?yàn)樵诤竺娌恍枰褂胻itle實(shí)例,如果在其它地方我們還要訪問title,我們應(yīng)把它保存在一個(gè)實(shí)例屬性中。
注意那個(gè)實(shí)例名title,只是按照習(xí)慣要被使用,我們從來不會(huì)在代碼中使用這個(gè)名字。在我們的應(yīng)用程序中,我們都通過變量或?qū)傩詠碇赶蚪M件。在這個(gè)案例中,我們通過變量名title指向title實(shí)例,而不是通過它的實(shí)例名(這時(shí)變量名和實(shí)例名碰巧是相同的)。按照習(xí)慣,大部分的組件的實(shí)例名都與保存這個(gè)實(shí)例名的變量或?qū)傩韵嗥ヅ?。然而,沒有規(guī)定實(shí)例名要和變量或?qū)傩悦ヅ?,只有變量或?qū)嵗c我們的應(yīng)用程序有關(guān)(實(shí)例名被忽略)。
現(xiàn)在讓我們近處看一下常用于創(chuàng)建Label實(shí)例的代碼:
converter_mc.createClassObject(Label, "title", 0);
MovieClip類有沒有定義createClassObject( )方法,為什么能在MovieClip類的實(shí)例converter_mc里面調(diào)用createClassObject( )方法呢?因?yàn)樵谶\(yùn)行時(shí),通過V2組件架構(gòu)(連同各種各樣的方法)把這個(gè)方法加入到了MovieClip類里。只有一個(gè)類聲明為動(dòng)態(tài)時(shí),才能在運(yùn)行時(shí)把方法或?qū)傩约拥竭@個(gè)類里面,就像在MovieClip類里面定義一樣。
因?yàn)槲覀兪峭ㄟ^mc來訪問createClassObject( )方法,所以我們也不用擔(dān)心這個(gè)方法返回了一個(gè)數(shù)據(jù)類型為UIObject的對(duì)象。通過使用title變量,類型Label是不必需的。從理論上講,下面的代碼通常會(huì)出現(xiàn)類型不匹配的錯(cuò)誤,因?yàn)閏reateClassObject( )方法返回的是UIObject的類型,但是title的數(shù)據(jù)類型是Label。
var title:Label = converter_mc.createClassObject(Label, "title", 0);
然而,沒有錯(cuò)誤發(fā)生是因?yàn)轭愋蜋z查在運(yùn)行時(shí)對(duì)動(dòng)態(tài)加入的方法沒有進(jìn)行,但如果這個(gè)方法不是動(dòng)態(tài)加入的,如任何組件都有createClassObject( )方法,如果你在一個(gè)組件中調(diào)用createClassObject( )方法,就要進(jìn)行類型檢查,此時(shí)這個(gè)不匹配錯(cuò)誤就會(huì)發(fā)生。為了阻止一個(gè)編譯錯(cuò)誤,你必須指定返回值為你創(chuàng)建的對(duì)象的類型,例如,這里我們指定createClassObject( )方法的返回值為Label類型,如果converter_mc里用組件實(shí)例代替影片剪輯實(shí)例,下面的類型轉(zhuǎn)換是必需的:
var title:Label = Label(converter_mc.createClassObject(Label, "title", 0));
現(xiàn)在,title實(shí)例已經(jīng)被創(chuàng)建,我們將調(diào)整它的屬性:
title.autoSize = "left";
title.text = "Canadian Currency Converter";
title.setStyle("color", 0x770000);
title.setStyle("fontSize", 16);
12.5.3 說明(Label)組件
要?jiǎng)?chuàng)建這個(gè)說明組件,我們將創(chuàng)建另一個(gè)Label組件,創(chuàng)建方法與title的類似,我們把label實(shí)例保存在名為instructions的變量中:
var instructions:Label = converter_mc.createClassObject(Label, "instructions", 1);
instructions.autoSize = "left";
instructions.text = "Enter Amount in Canadian Dollars";
instructions.move(instructions.x, title.y+title.height+5);
上述代碼的最后一行是把instructions實(shí)例放在低于title實(shí)例5像素的位置。
注:設(shè)置組件位置的方法只有move()方法,通過讀寫屬性x和y來設(shè)置組件的位置是沒有用的,要注意,組件支持x,y,width等屬性(沒有下劃線),而MovieClip實(shí)例支持_x等屬性(有下劃線)
12.3.5.4 輸入(TextInput)組件
隨著兩個(gè)Label的創(chuàng)建,我們把目光移向接受用戶輸入的TextInput組件,第一個(gè)TextInput組件創(chuàng)建的代碼如下:
input = converter_mc.createClassObject(TextInput, "input", 2);
input.setSize(200, 25);
input.move(input.x, instructions.y+instructions.height);
input.restrict = "0-9.";
注:設(shè)置組件的尺寸只能通過setSize()方法,不能使用width和height屬性。
接下去要定義當(dāng)用戶按下ENTER鍵時(shí)發(fā)生什么,首先創(chuàng)建一個(gè)事件偵聽器對(duì)象,用來接收事件:
var enterHandler:Object = new Object( );
在這個(gè)對(duì)象實(shí)例里面,定義一個(gè)enter()方法,當(dāng)用戶按下ENTER鍵時(shí),這個(gè)方法會(huì)自動(dòng)被調(diào)用:
enterHandler.enter = function(e:Object) {
thisConverter.convert();
}
enter()方法通過thisConverter變量訪問了convert()方法,當(dāng)input實(shí)例存在時(shí),變量thisConverter是可以被嵌套的enterHandler.enter()方法訪問:
最后,注冊(cè)對(duì)象實(shí)例接收enter事件:
input.addEventListener("enter", enterHandler);
雖然使用一個(gè)對(duì)象實(shí)例處理事件是很合理的,但在更復(fù)雜的例子中,一個(gè)事件偵聽器對(duì)象有充分的理由是一個(gè)獨(dú)立的類的實(shí)例,不管怎樣,當(dāng)一個(gè)單一的事件產(chǎn)生單一的響應(yīng)時(shí),用事件處理函數(shù)比用對(duì)象實(shí)例處理事件更有可能的。在的應(yīng)用程序轉(zhuǎn)換按鈕中,我們將使用事件處理函數(shù)來處理事件。后面我們也將學(xué)習(xí)MM為什么不鼓勵(lì)使用事件處理函數(shù)。在這個(gè)特殊的enterHandler.enter()的例子中,由于Textinput類不能使用事件處理函數(shù)的bug,我們被迫使用一個(gè)偵聽器對(duì)象。
12.3.5.5 貨幣拾取(ComboBox)組件
現(xiàn)在我們準(zhǔn)備一個(gè)下拉菜單,來列出讓用戶進(jìn)行轉(zhuǎn)換的貨幣類型,ComboBox組件保存在currencyPicker屬性中:
currencyPicker = converter_mc.createClassObject(ComboBox, "picker", 3);
currencyPicker.setSize(200, currencyPicker.height);
currencyPicker.move(currencyPicker.x, input.y+input.height+10);
然后列出用戶可以選擇的貨幣類型,其中data屬性將被convert( )方法使用:
currencyPicker.dataProvider = [
{label:"Select Target Currency", data:null},
{label:"Canadian to U.S. Dollar", data:"US"},
{label:"Canadian to UK Pound Sterling", data:"UK"},
{label:"Canadian to EURO", data:"EU"}];
12.3.5.5 轉(zhuǎn)換按鈕(Button)組件
在前面我們已經(jīng)設(shè)置一個(gè)按鍵事件(ENTER),現(xiàn)在要為不喜歡使用按鈕的用戶增加一個(gè)可見的轉(zhuǎn)換按鈕。
我們這時(shí)創(chuàng)建是的mx.controls.Button組件類的實(shí)例,注意要和Button符號(hào)的實(shí)例區(qū)別開來。因?yàn)槲覀冚^早的導(dǎo)入mx.controls.*包,編譯器就能知道它指向的是Button組件類的實(shí)例。
創(chuàng)建Button組件實(shí)例:
var convertButton:Button = converter_mc.createClassObject(Button, "convertButton", 4);
convertButton.move(currencyPicker.x+currencyPicker.width+5, currencyPicker.y);
convertButton.label = "Convert!";
最后,我們用事件處理函數(shù)定義一個(gè)click事件:
convertButton.clickHandler = function(e:Object) {
thisConverter.convert();
};
上面的代碼示例了組件事件使用的一種方法,它定義了一個(gè)的匿名函數(shù),當(dāng)click事件發(fā)生時(shí),這個(gè)函數(shù)能自動(dòng)調(diào)用。
由于匿名函數(shù)是嵌套在buildConverter( )方法的里面,它已經(jīng)訪問了buildConverter( )的局部變量,因此,通過局部變量thisConverter ,convertButton能指向當(dāng)前的CurrencyConverter類的實(shí)例。
13.3.5.7 結(jié)果(TextArea)組件
我們的界面幾乎已經(jīng)完成了,還需要一個(gè)TextArea組件實(shí)例顯示貨幣轉(zhuǎn)換的結(jié)果,下面是創(chuàng)建的代碼:
result = converter_mc.createClassObject(TextArea, "result", 5);
result.setSize(200, 25);
result.move(result.x, currencyPicker.y+currencyPicker.height+10);
為了阻止用戶替換TextArea組件實(shí)例中的內(nèi)容,要加上下面的代碼,因?yàn)樗笔≈凳莟rue,表示可編輯的:
result.editable = false;
12.3.6 基于用戶的貨幣轉(zhuǎn)換
在前面,我們創(chuàng)建了用戶界面,當(dāng)用戶click轉(zhuǎn)換按鈕時(shí),會(huì)調(diào)用convert( )方法,這個(gè)方法能夠進(jìn)行轉(zhuǎn)換貨幣,也能顯示出錯(cuò)誤信息,方法中的代碼提供了組件怎樣被訪問和操作的一個(gè)很好的例子,代碼如下:
這個(gè)類方法首先創(chuàng)建兩個(gè)局部變量,convertedAmount用來保存轉(zhuǎn)換后的貨幣值,origAmount用來保存用戶輸入的值:
var convertedAmount:Number;
var origAmount:Number = parseFloat(input.text);
輸入框的內(nèi)容可能是空的,或者它不是一個(gè)有效的值,因此下面代碼的任務(wù)是檢查是否把這個(gè)值進(jìn)行了String到Number的轉(zhuǎn)換,如果轉(zhuǎn)換不成功,origAmount的值將是NaN,因此當(dāng)這個(gè)值是NaN時(shí),我們說它不是一個(gè)有效值。
if (!isNaN(origAmount)) {
如果這個(gè)值是有效的,我們就檢查currencyPicker.selectedItem.data(下拉列表中被選中的貨幣值), selectedItem屬性保存了一個(gè)對(duì)ComboBBox中當(dāng)前選項(xiàng)的指向,它是前面創(chuàng)建的dataProvider數(shù)組的一個(gè)對(duì)象,為了確定哪個(gè)選項(xiàng)被選中,我們參考對(duì)象的data屬性,它可能是null, "US," "UK," or "EU."中的一個(gè),如果data屬性為null,說明沒有選項(xiàng)被選中,我們就不用進(jìn)行轉(zhuǎn)換貨幣:
if (currencyPicker.selectedItem.data != null) {
如果是其它的幾個(gè)之一,我們用switch語句來確定到底是哪個(gè)值,根據(jù)這個(gè)值進(jìn)行相應(yīng)的轉(zhuǎn)換:
switch (currencyPicker.selectedItem.data) {
case "US" :
convertedAmount = origAmount/CurrencyConverter.rateUS;
break;
case "UK" :
convertedAmount = origAmount/CurrencyConverter.rateUK;
break;
case "EU" :
convertedAmount = origAmount/CurrencyConverter.rateEU;
break;
}
一旦轉(zhuǎn)換成功,我們將結(jié)果列出:
result.text = "Result: "+convertedAmount;
當(dāng)沒有貨幣被選中時(shí),我們提示用戶進(jìn)行選擇:
result.text = "請(qǐng)選擇一種貨幣";
如果是一個(gè)無效值,提示用戶輸入一個(gè)有效值:
result.text = "當(dāng)前值是無效的";
12.3.7 導(dǎo)出最終的應(yīng)用程序
略
導(dǎo)出時(shí)要注意版本,V2 組件要求播放器的版本是6.0.79.0 或更高,但我在6.0.40.0中測(cè)試時(shí),應(yīng)用程序能很好的執(zhí)行。
這章討論在許多工程中和開發(fā)者之間共享類庫的各種方法。在開始討論之前,要注意:flash的類分配特征并不是很精煉,到目前為止,共享類最簡單的方法是發(fā)布源代碼。在講不通過發(fā)布源代碼怎樣共享類之前,我們將先講這種最簡單的方法,因?yàn)楫?dāng)你出售一個(gè)專業(yè)類庫的時(shí)候可能要那樣做。
類庫是一個(gè)通常的程序術(shù)語,只是簡單的指一群類,不要把它和fla文件庫、庫面板、共享庫(在創(chuàng)作時(shí)共享庫資源)和運(yùn)行共享庫(在運(yùn)行時(shí)共享庫資源)混合起來,這些術(shù)語中的每一個(gè)都是唯一的,這不是當(dāng)前討論的內(nèi)容。
類庫只是程序員用來發(fā)布一群類到一個(gè)團(tuán)隊(duì)或其它地方的行話,在另一個(gè)方面,包是一個(gè)正式的用來定義類的語法命名空間(為了防止和其它類的命名沖突)。
類庫可能通過as、swf和swc的形式分配給其它開發(fā)者,這章將討論這三種方法。
14.1 共享類的源文件
共享類庫最可能的原因是為了在多個(gè)工程中重復(fù)使用它們。例如,假設(shè)你正在做一個(gè)名叫Spider Services的網(wǎng)上商店(http://www.spiderservices.com/),你已經(jīng)寫了一個(gè)處理各種文本效果的TextAnimation類,你要在你做的兩個(gè)站點(diǎn)中使用這個(gè)類,比在兩個(gè)工程的文件夾中放置一份拷貝更好的方法是,你把類放在中間,每個(gè)工程只是指向它,例如,在windows中,你應(yīng)該把類保存在下面的目錄中:
c:\data\actionscript\com\spiderservices\effects\TextAnimation.as
為了使這個(gè)類能被兩個(gè)工程都能訪問,你應(yīng)把c:\data\actionscript增加到flash的全局類路徑中。
如果在你的團(tuán)隊(duì)中有多個(gè)成員,你可能認(rèn)為把類放在中間服務(wù)器是方便的,這樣每個(gè)人都可以使用它。例如:你可能要把所有的共享類都放在叫codecentral的服務(wù)器上,存放目錄與你公司域名相配(\com\spiderservices)。
\\codecentral\actionscript\com\spiderservices\effects\TextAnimation.as
這個(gè)方法是極度危險(xiǎn)的,也是不推薦使用的。
注:
如果你把類放在一個(gè)中間服務(wù)器上并允許其它開發(fā)者直接修改,一個(gè)開發(fā)者容易覆蓋另一個(gè)開發(fā)者的修改,而且,如果服務(wù)器和個(gè)人電腦的時(shí)鐘不同步,在編譯時(shí),類的最后一個(gè)版本可能不會(huì)被包括在影片內(nèi)。為了避免這個(gè)問題,你將總是使用版本控制軟件去管理你的類文件。一個(gè)流行的選擇是CVS (見 www.cvshome.org)。
在一個(gè)大的工程中,你可能使用一些工具使swf的輸出自動(dòng)化,例如Apache Ant (http://ant.apache.org).,為了那樣做,你將執(zhí)行JSFL告訴flash為每個(gè)fla創(chuàng)建swf文件,這些內(nèi)容超出了本書的范圍,但這有一個(gè)例子
// Code in exportPetSupplies.jsfl:
// ===============================
// Open the .fla file.
var doc = fl.openDocument("file:///c|/data/projects/pet/petsupplies.fla");
// Export the .swf file.
doc.exportSWF("file:///c|/data/projects/pet/petsupplies.swf", true);
// Quit the Flash MX 2004 authoring tool (optional).
fl.quit(false);
// Command issued on command line from /pet/ directory:
// ====================================================
"c:\program files\macromedia\flash mx 2004\flash.exe" exportPetSupplies.jsfl
14.1.1 在運(yùn)行時(shí)加載類
當(dāng)使用同一個(gè)類制作多個(gè)swf文件時(shí),把類編譯到每個(gè)swf中是一種空間浪費(fèi),當(dāng)文件的尺寸有關(guān)系時(shí),為阻止這種事情發(fā)生,你可能把類庫放到一個(gè)單獨(dú)的swf文件并在運(yùn)行時(shí)加載它,一旦這個(gè)庫在第一時(shí)間加載,它可能隱藏在用戶的機(jī)器中,然后不需重新下載它就能被其它swf利用。
注:一個(gè)類庫在運(yùn)行時(shí)加載稱為動(dòng)態(tài)類庫
為了創(chuàng)建這個(gè)動(dòng)態(tài)類庫,我們編譯類庫到一個(gè)swf文件中,然后使用loadMovie()把它加載到任何一個(gè)需要類庫的swf文件中。然而,為了使這種技術(shù)能正常工作,我們必須確定在庫中的類被排除在加載它們的影片中。為了實(shí)現(xiàn)阻止類被編譯到加載它們的影片中,我們使用排除XML文件。這個(gè)xml能讓fla文件本地訪問類,但能阻止這些類被包含在輸入的swf文件,這樣允許在運(yùn)行時(shí)被加載。
為了創(chuàng)建運(yùn)行加載的類庫,我們返回到前面的例子:
下面這些步驟是必須要做的:
1、在類庫中創(chuàng)建類
2、創(chuàng)建含類庫的swf文件
3、創(chuàng)建加載含類庫swf文件的影片
4、創(chuàng)建排除xml文件
14.1.1.1、在類庫中創(chuàng)建類
創(chuàng)建一個(gè)類庫的第一步是創(chuàng)建它包含的類,我們的角色類是TextAnimation,保存在c:\data\actionscript\com\spiderservices\effects\TextAnimation.as,對(duì)于這個(gè)例子,我們的焦點(diǎn)是類庫的建立 ,因此我們沒給出真實(shí)的類代碼,只在構(gòu)造函數(shù)中提供了一個(gè)trace()來檢查這具類是否在工作。
class com.spiderservices.effects.TextAnimation {
public function TextAnimation ( ) {
trace("Imagine a text effect with great majesty.");
}
}
現(xiàn)在類庫已經(jīng)建好,下一步創(chuàng)建含類的swf文件
14.1.1.2、創(chuàng)建類庫(swf文件)
為了創(chuàng)建這個(gè)swf文件,跟隨以下步驟
1、創(chuàng)建目錄c:\data\spiderservices\spidercore。
2、增加全局類路徑c:\data\actionscript
3、建立一個(gè)fla文件,保存在c:\data\spiderservices\spidercore\spidercore_runtime.fla
4、第1幀輸入:
com.spiderservices.effects.TextAnimation
如果類庫中含有更多有類,這些類都應(yīng)列在第1幀,編譯器會(huì)自動(dòng)查找并包括所有有關(guān)的類(例如,在TextAnimation中使用了Tween,Tween類就會(huì)自動(dòng)的包括到swf文件中),這樣,我們就不用一個(gè)個(gè)導(dǎo)入TextAnimation類中所需的類。
5、在第2幀插入一關(guān)鍵幀,輸入:
6、在第2幀輸入代碼:
_parent.spidercoreLoaded();
stop();
7、輸出swf文件。
8、保存fla文件
類庫創(chuàng)建好后,就可以在任何一個(gè)影片中使用它們
14.4.1.3、創(chuàng)建加載類庫的影片
在這個(gè)例子中,加載spidercore_runtime.swf是公司的主頁,創(chuàng)建主頁影片:
1、增加目錄c:\data\spiderservices\barkys
2、新建一個(gè)fla文件,保存在c:\data\spiderservices\barkys\barkyshome.fla
3、在第1幀輸入:
import as.TextAnimation;
function spidercoreLoaded():Void {
var ta:TextAnimation = new TextAnimation();
}
// Load class library.
this.createEmptyMovieClip("spidercore", 0);
this.spidercore.loadMovie("../spidercore/spidercore_runtime.swf");
homepage這個(gè)影片是準(zhǔn)備用來使用類庫的,這里有個(gè)問題:如果在當(dāng)前使用,它會(huì)自動(dòng)包含TextAnimation類到影片中,我們可不想讓這種事情發(fā)生,因?yàn)槲覀円ㄟ^spidercore_runtime.swf來加載類。我們不需要加載兩次類,因此,需要?jiǎng)?chuàng)建一個(gè)特殊的xml文件,告訴編譯器不要把TextAnimation包含進(jìn)barkyshome.swf中。
你可能設(shè)想只通過移除c:\data\actionscript路徑,就能使TextAnimation類不被包含到barkyshome.swf中。事實(shí)上,就是可以的,但由于類型檢查的原因也阻止編譯器查找TextAnimation類,因此,類型錯(cuò)誤將發(fā)生,barkyshome.swf將不能被編譯,因此,雖然我們?cè)谶\(yùn)行時(shí)加載類,我們?nèi)孕柙趧?chuàng)作時(shí)訪問這些類。
14.1.14、創(chuàng)建xml文件
在這個(gè)文件中,指定哪些類將被編譯進(jìn)相關(guān)的swf文件中,我們將阻止在運(yùn)行時(shí)動(dòng)態(tài)加載的類編譯進(jìn)應(yīng)用的swf文件中。
1、創(chuàng)建一個(gè)名為barkyshome_exclude.xml文件,保存在c:\data\spiderservices\barkys\barkyshome_exclude.xml。
排除文件的精確名字是很重要的,這必須與應(yīng)用它的fla文件名正確匹配。
2、這個(gè)排除文件阻止指定類被編譯進(jìn)相關(guān)的swf文件,為了阻止TextAnimation類被編譯到swf文件,在barkyshome_exclude.xml中增加代碼:
<excludeAssets>
<asset name="com.spiderservices.effects.TextAnimation"></asset>
</excludeAssets>
這時(shí)有一個(gè)假定的排除文件,顯示怎樣來排除多個(gè)類,它排除了下面列出的三個(gè)類
<excludeAssets>
<asset name="com.spiderservices.effects.TextAnimation"></asset>
<asset name="com.spiderservices.effects.Tween"></asset>
<asset name="com.spiderservices.util.Randomizer"></asset>
</excludeAssets>
3、保存
在<asset>標(biāo)簽中通過列出TextAnimation類,我們強(qiáng)迫它排除在barkyshome.swf文件中。在spidercore_runtime.swf類庫中的每個(gè)類都應(yīng)該列在<asset>標(biāo)簽中。
注:編譯不會(huì)自動(dòng)排除依賴的類,例如:要spidercore類庫包含一個(gè)被TextAnimation 使用的Tween類,但barkyshome_exclude.xml沒有在<asset>標(biāo)簽列出此類,Tween將被包含在barkyshome.swf中。
我們的spidercore類庫現(xiàn)在已經(jīng)準(zhǔn)備好使用了
14.1.1.5 測(cè)試
通過輸出barkyshome .swf文件來測(cè)試這個(gè)類庫,barkyshome.sw將不包含TextAnimation類,但通過動(dòng)態(tài)類庫spidercore_runtime.swf可以訪問它,記住,類庫能加載是因?yàn)槲覀兏嬖V它:
// Load class library.
this.createEmptyMovieClip("spidercore", 0);
this.spidercore.loadMovie("../spidercore/spidercore_runtime.swf");
你將在輸出面板中看到:
Imagine a text effect with great majesty.
如果我們想要加載另一個(gè)類庫,第2版本的類庫不會(huì)覆蓋第一個(gè)版本的,它將被hu略,為了防止命名沖突,特別我們使用動(dòng)態(tài)類庫的時(shí)候,讓你的類在有唯一名字的包里。