本文将要介紹的内容會比較“有趣”,因為我們可以看到非常熟悉的視窗、按鈕、動畫等效果,而這些圖形界面元素不僅會讓開發者感到更“有趣”,對最終使用者也是一種誘惑,使用者總是喜歡功能豐富、操作簡單的應用,圖形使用者界面的程式就可以滿足使用者的這種渴望。
Java使用AWT和Swing類完成圖形使用者界面程式設計,其中AWT的全稱是抽象視窗工具集(Abstract Window Toolkit),它是Sun最早提供的GUI庫,這個GUI庫提供了一些基本功能,但這個GUI庫的功能比較有限,是以後來又提供了Swing庫。通過使用AWT和Swing提供的圖形界面元件庫,Java的圖形使用者界面程式設計非常簡單,程式隻要依次建立所需的圖形元件,并以合适的方式将這些元件組織在一起,就可以開發出非常美觀的使用者界面。
程式以一種“搭積木”的方式将這些圖形使用者元件組織在一起,就是實際可用的圖形使用者界面,但這些圖形使用者界面還不能與使用者互動,為了實作圖形使用者界面的使用者互動操作,程式還應為程式提供事件處理,事件處理負責讓程式可以響應使用者動作。
<b><b>GUI</b><b>(圖形使用者界面)和AWT</b></b>
前面介紹的所有程式都基于指令行,基于指令行的程式可能隻有一些“專業”計算機人士才會使用。例如前面編寫的五子棋、×××等程式,恐怕隻有我們自己才願意玩這麼“糟糕”的遊戲,很少有最終使用者願意對着黑糊糊的指令行界面敲指令。
相反,如果為程式提供直覺的圖形使用者界面(Graphics User Interface,簡稱為GUI),最終使用者通過滑鼠拖動、單擊等動作就可以操作整個應用,整個應用程式就會受歡迎得多(實際上,Windows之是以廣為人知,其最初的吸引力就是來自于它所提供的圖形使用者界面)。作為一個程式設計者,必須優先考慮使用者的感受,一定要讓使用者感到“爽”,我們的程式才會被需要、被使用,這樣的程式才有價值。
當JDK1.0釋出時,Sun提供了一個基本的GUI類庫,這個GUI類庫希望可以在所有平台下都能運作,這套基本類庫被稱為“抽象視窗工具集(Abstract Window Toolkit)",它為Java應用程式提供了基本的圖形元件。AWT是視窗架構,它從不同平台的視窗系統中抽取出共同元件,當程式運作時,将這些元件的建立和動作委托給程式所在的運作平台。簡而言之,當使用AWT編寫圖形界面應用時,程式僅指定了界面元件的位置和行為,并未提供真正的實作,JVM調用作業系統本地的圖形界面來建立和平台一緻的對等體。
使用AWT建立的圖形界面應用和所在運作平台有相同的界面風格,比如在Windows作業系統上,它就表現出Windows風格;在UNIX作業系統上,它就表現出UNIX風格。Sun希望采用這種方式來實作“Write Once, Run Anywhere”的目标。
但實際應用中,AWT出現了如下幾個問題:
1、使用AWT作出的圖形使用者界面在所有平台上都顯得很醜陋,功能也非常有限。
2、AWT為了迎合所有主流作業系統的界面設計,AWT元件隻能使用這些作業系統上圖形界面元件的交集,是以不能使用特定作業系統上複雜的圖形界面元件,最多隻能使用四種字型。
3、AW下用的是非常笨拙的、非面向對象的程式設計模式。
1996年,Netscape公司開發了一套工作方式完全不同的GUI庫,簡稱為IFC (Internet Foundation Classes),這套GUI庫的所有圖形界面元件,例如文本框、按鈕等都是繪制在空白視窗上的,隻有視窗本身需要借助于作業系統的視窗實作。IFC真正實作了各種平台上的界面一緻。不久,Sun和Netscape合作完善了這種方法,并建立了一個新的使用者界面庫:Swing, AWT, Swing、輔助功能API, 2D API以及拖放API共同組成了JFC (Java Foundation Classes,即Java基礎類庫),其中Swing元件全面替代了Java1.0中AWT元件,但保留了Java 1.1的AWT事件模型。總體上,AWT是圖形使用者界面程式設計的基礎,Swing元件替換了絕大部分AWT元件,對AWT圖形使用者界面程式設計有幾号的補充和加強。
Swing并沒有完全替代AWT元件,而是建立在AWT基礎之上,Swing僅提供了能力更強大的使用者界面元件,即使是完全采用Swing編寫的GUI程式中,依然需要使用AWT的事件處理機制。AWT元件在Swing裡将有對應的實作,二者用法基本相似。
<b><b>AWT</b><b>容器</b></b>
如果從程式員的角度來看一個視窗時,這個視窗不是一個整體(有點庖丁解牛的感覺),而是由多個部分組合而成的。
任何視窗都可被分解成一個空的容器,容器裡盛裝了大量基本元件,通過設定這些基本元件的大小、位置等屬性,就可以将該空容器和基本元件組成一個整體的視窗。實際上,在筆者看來,圖形界面程式設計非常簡單,它非常類似于我們兒時玩的拼圖遊戲,容器類似于拼圖的“主機闆”,而普通元件(如Button, List之類)則類似于拼圖的圖塊。建立圖形使用者界面的過程就是完成拼圖的過程。
容器(Container)是Component的子類,是以容器對象本身也是一個元件,具有元件的所有性質,可以調用Component的所有方法,Component有如下幾個常用方法來設定元件的大小、位置和可見性等。
1、setLocation(int x, int y):設定元件位置。
2、setSize(int width, int height):設定元件的大小。
3、setBounds(int x, int y, int width, int height):同時設定元件的位置、大小。
4、setVisible(Boolean b):設定該元件的可見性。
除此之外,容器還具有能盛裝其他元件的功能,容器類(Container)主要提供了如下幾個常用方法來通路容器裡的元件:
1、Component add(Component comp):向容器中添加其他元件(該元件既可以是普通元件,也可以是容器),并傳回被添加的元件。
2、Component getComponentAt(int x, int y):傳回指定點的元件。
3、int getComponentCount():傳回該容器内元件的數量。
4、Component[] getComponents():傳回該容器内的所有元件。
AWT主要提供了兩種主要的容器類型:
1、Window:可獨立存在的頂級視窗
2、Panel:可作為容器容納其他元件,但不能獨立存在,必須被添加到其他容器中(如Window, Panel或者Applet等)。
Frame、Panel、ScrolPane、Dialog是AWT程式設計中常用的元件,其中Frame代表常見的視窗,它是Window類的子類,具有如下幾個特征;
1、Frame對象有标題,允許通過拖拉來改變視窗的位置、大小。
2、初始化時為不可見,可用setVisible(true)使其顯示出來。
3、預設使用BorderLayout作為其布局管理器。
<b><b>布局管理器</b></b>
為了使生成的圖形使用者界面具有良好的平台無關性,Java語言中,提供了布局管理器這個工具來管理元件在容器中的布局,而不使用直接設定元件位置和大小的方式。例如我們通過如下定義了一個标簽(Label):
Label hello=newLabel(“Hello Java”);
為了讓這個hello标簽裡剛好可以容納這個”Hello Java”字元串(既沒有備援空間,也沒有内容被遮擋),也就是實作該标簽的最佳大小,Windows可能應該設定為長100像素,高20像素即可,但換到Unix上,則可能需要設定為長120像素,高24像素。那麼一個應用程式從Windows移植到Unix上時,程式需要做大量工作來調整圖形界面。
對于不同的元件而言,它們都有一個最佳大小(既沒有備援空間,也沒有内容被遮擋),這個最佳大小通常是平台相關的,程式在不同平台上運作時,相同内容的大小可能不一樣。如果讓程式手動控制每個元件的大小、位置,這将給程式設計帶來巨大的困難,為了解決這個問題,Java提供了LayoutManager來解決這些問題,LayoutManager可以根據運作平台來調整元件的大小,程式員要做的,隻是為容器選擇合适的布局管理器。
所有的AWT容器都有預設的布局管理器,如果沒有為容器指定布局管理器,該容器使用預設的布局管理器。為容器指定布局管理器通過調用容器對象的setLayoutManager(LayoutManager lm)方法來完成。如下代碼所示:
c.setLayoutManager(new XxxLayout());
AWT提供了F1owLayout, BorderLayout, GridLayout, GridBigLayout, CardLayout五個常用的布局管理器,Swing還提供了一個BoxLayout布局管理器。下面将詳細介紹這幾個布局管理器。