?? chapter13.htm
字號:
可根據需要設置任意多個這樣的參數。<br>
在簡單的程序片中,我們要做的唯一事情是按上述形式在Web頁中設置一個程序片標記(applet),令其裝載和運行程序片。<br>
<br>
13.2.1 程序片的測試<br>
我們可在不必建立網絡連接的前提下進行一次簡單的測試,方法是啟動我們的Web瀏覽器,然后打開包含了程序片標簽的HTML文件(Sun公司的JDK同樣包括一個稱為“程序片觀察器”的工具,它能挑出html文件的<applet>標記,并運行這個程序片,不必顯示周圍的HTML文本——注釋②)。html文件載入后,瀏覽器會發現程序片的標簽,并查找由code值指定的.class文件。當然,它會先在CLASSPATH(類路徑)中尋找,如果在CLASSPATH下找不到類文件,就在WEB瀏覽器狀態欄給出一個錯誤信息,告知不能找到.class文件。<br>
<br>
②;由于程序片觀察器會忽略除APPLET標記之外的任何東西,所以可將那些標記作為注釋置入Java源碼:<br>
// <applet code=MyApplet.class width=200 height=100></applet><br>
這樣就可直接執行“appletviewer MyApplet.java”,不必再創建小的HTML文件來完成測試。<br>
<br>
若想在Web站點上試驗,還會碰到另一些麻煩。首先,我們必須有一個Web站點,這對大多數人來說都意味著位于遠程地點的一家服務提供商(ISP)。然后必須通過某種途徑將HTML文件和.class文件從自己的站點移至ISP機器上正確的目錄(WWW目錄)。這一般是通過采用“文件傳輸協議”(FTP)的程序來做成的,網上可找到許多這樣的免費程序。所以我們要做的全部事情似乎就是用FTP協議將文件移至ISP的機器,然后用自己的瀏覽器連接網站和HTML文件;假如程序片正確裝載和執行,就表明大功告成。但真是這樣嗎?<br>
但這兒我們可能會受到愚弄。假如Web瀏覽器在服務器上找不到.class文件,就會在你的本地機器上搜尋CLASSPATH。所以程序片或許根本不能從服務器上正確地裝載,但在你看來卻是一切正常的,因為瀏覽器在你的機器上找到了它需要的東西。但在其他人訪問時,他們的瀏覽器就無法找到那些類文件。所以在測試時,必須確定已從自己的機器刪除了相關的.class文件,以確保測試結果的真實。<br>
我自己就遇到過這樣的一個問題。當時是將程序片置入一個package(包)中。上載了HTML文件和程序片后,由于包名的問題,程序片的服務器路徑似乎陷入了混亂。但是,我的瀏覽器在本地類路徑(CLASSPATH)中找到了它。這樣一來,我就成了能夠成功裝載程序片的唯一一個人。后來我花了一些時間才發現原來是package語句有誤。一般地,應該將package語句置于程序片的外部。<br>
<br>
13.2.2 一個更圖形化的例子<br>
這個程序不會太令人緊張,所以讓我們試著增加一些有趣的圖形組件。<br>
<br>
594頁程序<br>
<br>
這個程序用一個方框將字符串包圍起來。當然,所有數字都是“硬編碼”的(指數字固定于程序內部),并以像素為基礎。所以在一些機器上,框會正好將字串圍住;而在另一些機器上,也許根本看不見這個框,因為不同機器安裝的字體也會有所區別。<br>
對Graphic類而言,可在幫助文檔中找到另一些有趣的內容。大多數涉及圖形的活動都是很有趣的,所有我將更多的試驗留給讀者自己去進行。<br>
<br>
13.2.3 框架方法的演示<br>
觀看框架方法的實際運作是相當有趣的(這個例子只使用init(),start()和stop(),因為paint()和destroy()非常簡單,很容易就能掌握)。下面的程序片將跟蹤這些方法調用的次數,并用paint()將其顯示出來:<br>
<br>
595頁程序<br>
<br>
正常情況下,當我們過載一個方法時,需檢查自己是否需要調用方法的基礎類版本,這是十分重要的。例如,使用init()時可能需要調用super.init()。然而,Applet文檔特別指出init()、start()和stop()在Applet中沒有用處,所以這里不需要調用它們。<br>
試驗這個程序片時,會發現假如最小化WEB瀏覽器,或者用另一個窗口將其覆蓋,那么就不能再調用stop()和start()(這一行為會隨著不同的實現方案變化;可考慮將Web瀏覽器的行為同程序片觀察器的行為對照一下)。調用唯一發生的場合是在我們轉移到一個不同的Web頁,然后返回包含了程序片的那個頁時。<br>
<br>
13.3 制作按鈕<br>
制作一個按鈕非常簡單:只需要調用Button構建器,并指定想在按鈕上出現的標簽就行了(如果不想要標簽,亦可使用默認構建器,但那種情況極少出現)。可參照后面的程序為按鈕創建一個句柄,以便以后能夠引用它。<br>
Button是一個組件,象它自己的小窗口一樣,會在更新時得以重繪。這意味著我們不必明確描繪一個按鈕或者其他任意種類的控件;只需將它們納入窗體,以后的描繪工作會由它們自行負責。所以為了將一個按鈕置入窗體,需要過載init()方法,而不是過載paint():<br>
<br>
596頁程序<br>
<br>
但這還不足以創建Button(或其他任何控件)。必須同時調用Applet add()方法,令按鈕放置在程序片的窗體中。這看起來似乎比實際簡單得多,因為對add()的調用實際會(間接地)決定將控件放在窗體的什么地方。對窗體布局的控件馬上就要講到。<br>
<br>
13.4 捕獲事件<br>
大家可注意到假如編譯和運行上面的程序片,按下按鈕后不會發生任何事情。必須進入程序片內部,編寫用于決定要發生什么事情的代碼。對于由事件驅動的程序設計,它的基本目標就是用代碼捕獲發生的事件,并由代碼對那些事件作出響應。事實上,GUI的大部分內容都是圍繞這種事件驅動的程序設計展開的。<br>
經過本書前面的學習,大家應該有了面向對象程序設計的一些基礎,此時可能會想到應當有一些面向對象的方法來專門控制事件。例如,也許不得不繼承每個按鈕,并過載一些“按鈕按下”方法(盡管這顯得非常麻煩有有限)。大家也可能認為存在一些主控“事件”類,其中為希望響應的每個事件都包含了一個方法。<br>
在對象以前,事件控制的典型方式是switch語句。每個事件都對應一個獨一無二的整數編號;而且在主事件控制方法中,需要專門為那個值寫一個switch。<br>
Java 1.0的AWT沒有采用任何面向對象的手段。此外,它也沒有使用switch語句,沒有打算依靠那些分配給事件的數字。相反,我們必須創建if語句的一個嵌套系列。通過if語句,我們需要嘗試做的事情是偵測到作為事件“目標”的對象。換言之,那是我們關心的全部內容——假如某個按鈕是一個事件的目標,那么它肯定是一次鼠標點擊,并要基于那個假設繼續下去。但是,事件里也可能包含了其他信息。例如,假如想調查一次鼠標點擊的像素位置,以便畫一條引向那個位置的線,那么Event對象里就會包含那個位置的信息(也要注意Java
1.0的組件只能產生有限種類的事件,而Java 1.1和Swing/JFC組件則可產生完整的一系列事件)。<br>
Java 1.0版的AWT方法串聯的條件語句中存在action()方法的調用。雖然整個Java
1.0版的事件模型不兼容Java 1.1版,但它在還不支持Java1.1版的機器和運行簡單的程序片的系統中更廣泛地使用,忠告您使用它會變得非常的舒適,包括對下面使用的action()程序方法而言。<br>
action()擁有兩個自變量:第一個是事件的類型,包括所有的觸發調用action()的事件的有關信息。例如鼠標單擊、普通按鍵按下或釋放、特殊按鍵按下或釋放、鼠標移動或者拖動、事件組件得到或丟失焦點,等等。第二個自變量通常是我們忽略的事件目標。第二個自變量封裝在事件目標中,所以它像一個自變量一樣的冗長。<br>
需調用action()時情況非常有限:將控件置入窗體時,一些類型的控件(按鈕、復選框、下拉列表單、菜單)會發生一種“標準行動”,從而隨相應的Event對象發起對action()的調用。比如對按鈕來說,一旦按鈕被按下,而且沒有再多按一次,就會調用它的action()方法。這種行為通常正是我們所希望的,因為這正是我們對一個按鈕正常觀感。但正如本章后面要講到的那樣,還可通過handleEvent()方法來處理其他許多類型的事件。<br>
前面的例程可進行一些擴展,以便象下面這樣控制按鈕的點擊:<br>
<br>
598頁程序<br>
<br>
為了解目標是什么,需要向Event對象詢問它的target(目標)成員是什么,然后用equals()方法檢查它是否與自己感興趣的目標對象句柄相符。為所有感興趣的對象寫好句柄后,必須在末尾的else語句中調用super.action(evt,
arg)方法。我們在第7章已經說過(有關多形性的那一章),此時調用的是我們過載過的方法,而非它的基礎類版本。然而,基礎類版本也針對我們不感興趣的所有情況提供了相應的控制代碼。除非明確進行,否則它們是不會得到調用的。返回值指出我們是否已經處理了它,所以假如確實與一個事件相符,就應返回true;否則就返回由基礎類event()返回的東西。<br>
對這個例子來說,最簡單的行動就是打印出到底是什么按鈕被按下。一些系統允許你彈出一個小消息窗口,但Java程序片卻防礙窗口的彈出。不過我們可以用調用Applet方法的getAppletContext()來訪問瀏覽器,然后用showStatus()在瀏覽器窗口底部的狀態欄上顯示一條信息(注釋③)。還可用同樣的方法打印出對事件的一段完整說明文字,方法是調用getAppletConext().showStatus(evt
+ "")。空字串會強制編譯器將evt轉換成一個字符串。這些報告對于測試和調試特別有用,因為瀏覽器可能會覆蓋我們的消息。<br>
<br>
③:ShowStatus()也屬于Applet的一個方法,所以可直接調用它,不必調用getAppletContext()。<br>
<br>
盡管看起來似乎很奇怪,但我們確實也能通過event()中的第二個參數將一個事件與按鈕上的文字相配。采用這種方法,上面的例子就變成了:<br>
<br>
599頁程序<br>
<br>
很難確切知道equals()方法在這兒要做什么。這種方法有一個很大的問題,就是開始使用這個新技術的Java程序員至少需要花費一個受挫折的時期來在比較按鈕上的文字時發現他們要么大寫了要么寫錯了(我就有這種經驗)。同樣,如果我們改變了按鈕上的文字,程序代碼將不再工作(但我們不會得到任何編譯時和運行時的信息)。所以如果可能,我們就得避免使用這種方法。<br>
<br>
13.5 文本字段<br>
“文本字段”是允許用戶輸入和編輯文字的一種線性區域。文本字段從文本組件那里繼承了讓我們選擇文字、讓我們像得到字符串一樣得到選擇的文字,得到或設置文字,設置文本字段是否可編輯以及連同我們從在線參考書中找到的相關方法。下面的例子將證明文本字段的其它功能;我們能注意到方法名是顯而易見的:<br>
<br>
600-601頁程序<br>
<br>
有幾種方法均可構建一個文本字段;其中之一是提供一個初始字符串,并設置字符域的大小。<br>
按下按鈕1
是得到我們用鼠標選擇的文字就是得到字段內所有的文字并轉換成字符串S。它也允許字段被編輯。按下按鈕2
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -