47 java程式設計思想——建立視窗和程式片 AWT
47.java程式設計思想——建立視窗和程式片 AWT
在Java 1.0 中,圖形使用者介面(GUI)庫最初的設計目標是讓程式設計師構建一個通用的GUI,使其在所有平臺上都能正常顯示。
但遺憾的是,這個目標並未達到。事實上,Java 1.0 版的“抽象Windows 工具包”(AWT)產生的是在各系統看來都同樣欠佳的圖形使用者介面。除此之外,它還限制我們只能使用四種字型,並且不能訪問作業系統中現有的高階GUI 元素。同時,Jave1.0 版的AWT程式設計模型也不是面向物件的,極不成熟。這類情況在Java1.1版的AWT 事件模型中得到了很好的改進,例如:更加清晰、面向物件的程式設計、遵循JavaBeans 的範例,以及一個可輕鬆建立可視程式設計環境的程式設計元件模型。Java1.2 為老的Java 1.0 AWT 添加了Java 基礎類(AWT),這是一個被稱為“Swing”的GUI的一部分。豐富的、易於使用和理解的Java Beans 能經過拖放操作(像手工程式設計一樣的好),創建出能使程式設計師滿意的GUI。軟體業的“3 次修訂版”規則看來對於程式設計語言也是成立的(一個產品除非經過第3 次修訂,否則不會盡如人意)。
Java 的主要設計目的之一是建立程式片,也就是建立執行在WEB 瀏覽器上的小應用程式。由於它們必須是安全的,所以程式片在執行時必須加以限制。無論怎樣,它們都是支援客戶端程式設計的強有力的工具,一個重要的應用便是在Web 上。
在一個程式片中程式設計會受到很多的限制,我們一般說它“在沙箱內”,這是由於Java 執行時一直會有某個東西——即Java 執行期安全系統——在監視著我們。Jave 1.1 為程式片提供了數字簽名,所以可選出能信賴的程式片去訪問主機。不過,我們也能跳出沙箱的限制寫出可靠的程式。在這種情況下,我們可訪問作業系統中的其他功能。AWT 也能用來為可靠的程式建立GUI 介面。
先學習使用老的AWT 工具,會與許多支援和使用AWT 的程式碼程式樣本相遇。儘管這有一些困難,但卻是必須的,因為我們必須用老的AWT 來維護和閱讀傳統的Java 程式碼。有時甚至需要我們編寫AWT 程式碼去支援不能從Java1.0 升級的環境。
大多數的例程都將展示程式片的建立,這並不僅僅是因為這非常的容易,更因為這是AWT 的主要作用。另外,當用AWT 建立一個可靠的程式時,我們將看到處理程式的不同之處,以及怎樣建立能在命令列和瀏覽器中執行的程式。
1 AWT
對於“老式”AWT,它最嚴重的缺點就是它無論在面向物件設計方面,還是在GUI 開發包設計方面,都有不盡如人意的表現。它使我們回到了程式設計的黑暗年代(換成其他話就是“拙劣的”、“可怕的”、“惡劣的”等等)。必須為執行每一個事件編寫程式碼,包括在其他環境中利用“資源”即可輕鬆完成的一些任務。
許多象這樣的問題在Java 1.1 裡都得到了緩解或排除,因為:
(1)Java 1.1 的新型AWT 是一個更好的程式設計模型,並向更好的庫設計邁出了可喜的一步。而Java Beans 則是那個庫的框架。
(2)“GUI 構建器”(可視程式設計環境)將適用於所有開發系統。在我們用圖形化工具將元件置入窗體的時候,Java Beans 和新的AWT 使GUI構建器能幫我們自動完成程式碼。其它元件技術如ActiveX 等也將以相同的形式支援。
既然如此,為什麼還要學習使用老的AWT 呢?原因很簡單,因為它的存在是個事實。就目前來說,這個事實對我們來說顯得有些不利,它涉及到面向物件庫設計的一個宗旨:一旦我們在庫中公佈一個元件,就再不能去掉它。如去掉它,就會損害別人已存在的程式碼。另外,當我們學習Java 和所有使用老AWT 的程式時,會發現有許多原來的程式碼使用的都是老式AWT。
AWT 必須能與固有作業系統的GUI 元件打交通,這意味著它需要執行一個程式片不可能做到的任務。一個不被信任的程式片在作業系統中不能作出任何直接呼叫,否則它會對使用者的機器做出不恰當的事情。一個不被信任的程式片不能訪問重要的功能。例如,“在螢幕上畫一個視窗”的唯一方法是通過呼叫擁有特殊介面和安全檢查的標準Java 庫。Sun 公司的原始模型建立的信任庫將僅僅供給Web 瀏覽器中的Java 系統信任關係自動授權器使用,自動授權器將控制怎樣進入到庫中去。
Java 1.1 版中的新模型是“信任程式碼”或“簽名程式碼”,因此一個特殊伺服器將校驗我們下載的、由規定的開發者使用的公共金鑰加密系統的程式碼。這樣我們就可知道程式碼從何而來,那真的是Bob 的程式碼,還是由某人偽裝成Bob 的程式碼。這並不能阻止Bob 犯錯誤或作某些惡意的事,但能防止Bob 逃避匿名製造計算機病毒的責任。一個數字簽名的程式片——“被信任的程式片”——在Java1.1 版能進入我們的機器並直接控制它,正像一些其它的應用程式從信任關係自動授權機中得到“信任”並安裝在我們的機器上。
這是老AWT 的所有特點。老的AWT 程式碼將一直存在,新的Java 程式設計者在從舊的書本中學習時將會遇到老的AWT 程式碼。同樣,老的AWT 也是值得去學習的,例如在一個只有少量庫的例程設計中。老的AWT 所包括的範圍在不考慮深度和列舉每一個程式和類,取而代之的是給了我們一個老AWT 設計的概貌。
2 基本程式片
庫通常按照它們的功能來進行組合。一些庫,例如使用過的,便中斷擱置起來。標準的Java 庫字串和向量類就是這樣的一個例子。其他的庫被特殊地設計,例如構建塊去建立其它的庫。庫中的某些類是應用程式的框架,其目的是協助我們構建應用程式,在提供類或類集的情況下產生每個特定應用程式的基本活動狀況。
然後,為我們定製活動狀況,必須繼承應用程式類並且廢棄程式的權益。應用程式框架的預設控制結構將在特定的時間呼叫我們廢棄的程式。應用程式的框架是“分離、改變和中止事件”的好例子,因為它總是努力去嘗試集中在被廢棄的所有特殊程式段。
程式片利用應用程式框架來建立。我們從類中繼承程式片,並且廢棄特定的程式。大多數時間我們必須考慮一些不得不執行的使程式片在WEB 頁面上建立和使用的重要方法。這些方法是:
方法 作用
init() 程式片第一次被建立,初次執行初始化程式片時呼叫
start() 每當程式片進入Web 瀏覽器中,並且允許程式片啟動它的常規操作時呼叫(特殊的程式片被stop()關閉);同樣在init()後呼叫paint() 基礎類Component 的一部分(繼承結構中上溯三級)。作為update() 的一部分呼叫,以便對程式片的畫布進行特殊的描繪
stop() 每次程式片從Web 瀏覽器的視線中離開時呼叫,使程式片能關閉代價高昂的操作;同樣在呼叫destroy()前呼叫
destroy() 程式片不再需要,將它從頁面中解除安裝時呼叫,以執行資源的最後清除工作
現在來看一看paint()方法。一旦Component(目前是程式片)決定自己需要更新,就會呼叫這個方法——可能是由於它再次迴轉螢幕,首次在螢幕上顯示,或者是由於其他視窗臨時覆蓋了你的Web 瀏覽器。此時程式片會呼叫它的update()方法(在基礎類Component 中定義),該方法會恢復一切該恢復的東西,而呼叫paint()正是這個過程的一部分。沒必要對paint()進行過載處理,但構建一個簡單的程式片無疑是方便的方法,所以我們首先從paint()方法開始。
update()呼叫paint()時,會向其傳遞指向Graphics 物件的一個控制代碼,那個物件代表準備在上面描繪(作
圖)的表面。這是非常重要的,因為我們受到專案元件的外觀的限制,因此不能畫到區域外,這可是一件好事,否則我們就會畫到線外去。在程式片的例子中,程式片的外觀就是這界定的區域。
圖形物件同樣有一系列我們可對其進行的操作。這些操作都與在畫布上作圖有關。所以其中的大部分都要涉及影象、幾何菜狀、圓弧等等的描繪(注意如果有興趣,可在Java 文件中找到更詳細的說明)。有些方法允許我們畫出字元,而其中最常用的就是drawString()。對於它,需指出自己想描繪的String(字串),並指定它在程式片作圖區域的起點。這個位置用畫素表示,所以它在不同的機器上看起來是不同的,但至少是可以移植的。
2.1 程式碼
import java.awt.*;
import java.applet.*;
public class Applet1 extends Applet {
public voidpaint(Graphics g){
g.drawString("First applet", 10, 10);
}
} /// :~
2.2 執行
如下圖1:
這個程式片不需要有一個main()。所有內容都封裝到應用程式框架中;我們將所有啟動程式碼都放在init()裡。
將這個程式放到一個Web 頁中執行,而只能在支援Java 的Web 瀏覽器中才能看到此頁。為了將一個程式片置入Web 頁,需要在那個Web 頁的程式碼中設定一個特殊的標記,以指示網頁裝載和執行程式片。這就是applet 標記,它在Applet1 中的樣子如下:
<applet
code=Applet1
width=200
height=200>
</applet>
其中,code 值指定了.class檔案的名字,程式片就駐留在那個檔案中。width 和height指定這個程式片的初始尺寸(如前所述,以畫素為單位)。還可將另一些東西放入applet 標記:用於在因特網上尋找其他.class 檔案的位置(codebase)、對齊和排列資訊(align)、使程式片相互間能夠通訊的一個特殊識別符號(name)以及用於提供程式片能接收的資訊的引數。引數採取下述形式:
<Paramname=識別符號 value="資訊">
可根據需要設定任意多個這樣的引數。
在簡單的程式片中,我們要做的唯一事情是按上述形式在Web 頁中設定一個程式片標記(applet),令其裝載和執行程式片。
在最新的ECLIPSE開發工具上可以直接除錯 APPLET的。
3 程式片的測試
我們可在不必建立網路連線的前提下進行一次簡單的測試,方法是啟動我們的Web 瀏覽器,然後開啟包含了程式片標籤的HTML 檔案(Sun 公司的JDK 同樣包括一個稱為“程式片觀察器”的工具,它能挑出html 檔案的<applet> 標記,並執行這個程式片,不必顯示周圍的HTML 文字)。html 檔案載入後,瀏覽器會發現程式片的標籤,並查詢由code 值指定的.class 檔案。當然,它會先在CLASSPATH(類路徑)中尋找,如果在CLASSPATH 下找不到類檔案,就在WEB 瀏覽器狀態列給出一個錯誤資訊,告知不能找到.class 檔案。
由於程式片觀察器會忽略除APPLET 標記之外的任何東西,所以可將那些標記作為註釋置入Java 原始碼:
// <appletcode=MyApplet.class width=200 height=100></applet>
這樣就可直接執行“appletviewer MyApplet.java”,不必再建立小的HTML 檔案來完成測試。
若想在Web 站點上試驗,還會碰到另一些麻煩。首先,我們必須有一個Web 站點,這對大多數人來說都意味著位於遠端地點的一家服務提供商(ISP)。然後必須通過某種途徑將HTML 檔案和.class 檔案從自己的站點移至ISP 機器上正確的目錄(WWW 目錄)。這一般是通過採用“檔案傳輸協議”(FTP)的程式來做成的,網上可找到許多這樣的免費程式。所以我們要做的全部事情似乎就是用FTP協議將檔案移至ISP 的機器,然後用自己的瀏覽器連線網站和HTML檔案;假如程式片正確裝載和執行,就表明大功告成。但真是這樣嗎?
但這兒我們可能會受到愚弄。假如Web 瀏覽器在伺服器上找不到.class 檔案,就會在你的本地機器上搜尋CLASSPATH。所以程式片或許根本不能從伺服器上正確地裝載,但在你看來卻是一切正常的,因為瀏覽器在你的機器上找到了它需要的東西。但在其他人訪問時,他們的瀏覽器就無法找到那些類檔案。所以在測試時,必須確定已從自己的機器刪除了相關的.class 檔案,以確保測試結果的真實。
4 圖形化的例子
4.1 程式碼2
import java.awt.*;
import java.applet.*;
public class Applet2 extends Applet {
public voidpaint(Graphics g){
g.drawString("Second applet", 10, 15);
g.draw3DRect(0, 0, 100, 20, true);
}
} /// :~
4.2 執行
如圖2:
這個程式用一個方框將字串包圍起來。當然,所有數字都是“硬編碼”的(指數字固定於程式內部),並以畫素為基礎。所以在一些機器上,框會正好將字串圍住;而在另一些機器上,也許根本看不見這個框,因為不同機器安裝的字型也會有所區別。
對Graphic 類而言,可在幫助文件中找到另一些有趣的內容。大多數涉及圖形的活動都是很有趣的。
5 框架方法的演示
觀看框架方法的實際運作是相當有趣的。下面的程式片將跟蹤這些方法呼叫的次數,並用paint()將其顯示出來:
5.1 程式碼3
import java.awt.*;
import java.applet.*;
public class Applet3 extends Applet {
String s;
int inits= 0;
int starts= 0;
int stops= 0;
public voidinit() {
inits++;
}
public voidstart() {
starts++;
}
public voidstop() {
stops++;
}
public voidpaint(Graphics g){
s = "inits:" + inits + ", starts: " + starts+ ", stops: " + stops;
g.drawString(s, 10, 10);
}
} /// :~
5.2 執行
正常情況下,當我們過載一個方法時,需檢查自己是否需要呼叫方法的基礎類版本,這是十分重要的。例如,使用init()時可能需要呼叫super.init()。然而,Applet 文件特別指出init()、start()和stop()在Applet 中沒有用處,所以這裡不需要呼叫它們。
試驗這個程式片時,會發現假如最小化WEB 瀏覽器,或者用另一個視窗將其覆蓋,那麼就不能再呼叫stop()和start()(這一行為會隨著不同的實現方案變化;可考慮將Web 瀏覽器的行為同程式片觀察器的行為對照一下)。呼叫唯一發生的場合是在我們轉移到一個不同的Web 頁,然後返回包含了程式片的那個頁時。
再分享一下我老師大神的人工智慧教程吧。零基礎!通俗易懂!風趣幽默!希望你也加入到我們人工智慧的隊伍中來!https://www.cnblogs.com/captainbed