?? chapter13.htm
字號:
這個例子同前面的例子相同除了增加了handleEvent()外簡直一模一樣。在程序中做了試驗來驗證是否列表框的選擇和非選擇存在。現(xiàn)在請記住,handleEvent()被程序片所過載,所以它能在窗體中任何存在,并且被其它的列表當成事件來處理。因此我們同樣必須通過試驗來觀察目標。(雖然在這個例子中,程序片中只有一個列表框所以我們能假設所有的列表框事件必須服務于列表框。這是一個不好的習慣,一旦其它的列表框加入,它就會變成程序中的一個缺陷。)如果列表框匹配一個我們感興趣的列表框,像前面的一樣的代碼將按上面的策略來運行。注意handleEvent()的窗體與action()的相同:如果我們處理一個單獨的事件,將返回真值,但如果我們對其它的一些事件不感興趣,通過handleEvent()我們必須返回super.handleEvent()值。這便是程序的核心,如果我們不那樣做,其它的任何一個事件處理代碼也不會被調用。例如,試注解在上面的代碼中返回super.handleEvent(evt)的值。我們將發(fā)現(xiàn)action()沒有被調用,當然那不是我們想得到的。對action()和handlEvent()而言,最重要的是跟著上面例子中的格式,并且當我們自己不處理事件時一直返回基礎類的方法版本信息。(在例子中我們將返回真值)。(幸運的是,這些類型的錯誤的僅屬于Java
1.0版,在本章后面將看到的新設計的Java 1.1消除了這些類型的錯誤。)<br>
在windows里,如果我們按下shift鍵,列表框自動允許我們做多個選擇。這非常的棒,因為它允許用戶做單個或多個的選擇而不是編程期間固定的。我們可能會認為我們變得更加的精明,并且當一個鼠標單擊被evt.shiftdown()產生時如果shift鍵是按下的將執(zhí)行我們自己的試驗程序。AWT的設計妨礙了我們-我們不得不去了解哪個項目被鼠標點擊時是否按下了shift鍵,所以我們能取消其余部分所有的選擇并且只選擇那一個。不管怎樣,我們是不可能在Java
1.0版中做出來的。(Java 1.1將所有的鼠標、鍵盤、焦點事件傳送到列表中,所以我們能夠完成它。)<br>
<br>
13.12 布局的控制<br>
在Java里該方法是安一個組件到一個窗體中去,它不同我們使用過的其它GUI系統(tǒng)。首先,它是全代碼的;沒有控制安放組件的“資源”。其次,該方法的組件被安放到一個被“布局管理器”控制的窗體中,由“布局管理器”根據(jù)我們add()它們的決定來安放組件。大小,形狀,組件位置與其它系統(tǒng)的布局管理器顯著的不同。另外,布局管理器使我們的程序片或應用程序適合窗口的大小,所以,如果窗口的尺寸改變(例如,在HTML頁面的程序片指定的規(guī)格),組件的大小,形狀和位置都會改變。<br>
程序片和幀類都是來源于包含和顯示組件的容器。(這個容器也是一個組件,所以它也能響應事件。)在容器中,調用setLayout()方法允許我選擇不同的布局管理器。<br>
在這節(jié)里我們將探索不同的布局管理器,并安放按鈕在它們之上。這里沒有捕捉按鈕的事件,正好可以演示如何布置這些按鈕。<br>
<br>
13.12.1 FlowLayout<br>
到目前為止,所有的程序片都被建立,看起來使用一些不可思議的內部邏輯來布置它們的組件。那是因為程序使用一個默認的方式:FlowLayout。這個簡單的“Flow”的組件安裝在窗體中,從左到右,直到頂部的空格全部再移去一行,并繼續(xù)循環(huán)這些組件。<br>
這里有一個例子明確地(當然也是多余地)設置一個程序片的布局管理器去FlowLayout,然后在窗體中安放按鈕。我們將注意到FlowLayout組件使用它們本來的大小。例如一個按鈕將會變得和它的字串符一樣的大小。<br>
<br>
614頁上程序<br>
<br>
所有組件將在FlowLayout中被壓縮為它們的最小尺寸,所以我們可能會得到一些奇怪的狀態(tài)。例如,一個標簽會合適它自已的字符串的尺寸,所以它會右對齊產生一個不變的顯示。<br>
<br>
13.12.2 BorderLayout<br>
布局管理器有四邊和中間區(qū)域的概念。當我們增加一些事物到使用BorderLayout的面板上時我們必須使用add()方法將一個字符串對象作為它的第一個自變量,并且字符串必須指定(正確的大寫)“North”(上),“South”(下),“west”(左),“East”(右)或者“Center”。如果我們拼寫錯誤或沒有大寫,就會得到一個編譯時的錯誤,并且程序片不會像你所期望的那樣運行。幸運的是,我們會很快發(fā)現(xiàn)在Java
1.1中有了更多改進。<br>
這是一個簡單的程序例子:<br>
<br>
614-615頁程序<br>
<br>
除了“Center”的每一個位置,當元素在其它空間內擴大到最大時,我們會把它壓縮到適合空間的最小尺寸。但是,“Center”擴大后只會占據(jù)中心位置。<br>
BorderLayout是應用程序和對話框的默認布局管理器。<br>
<br>
13.12.3 GridLayout<br>
GridLayout允許我們建立一個組件表。添加那些組件時,它們會按從左到右、從上到下的順序在網格中排列。在構建器里,需要指定自己希望的行、列數(shù),它們將按正比例展開。<br>
<br>
615頁下程序<br>
<br>
在這個例子里共有21個空位,但卻只有20個按鈕,最后的一個位置作留空處理;注意對GridLayout來說,并不存在什么“均衡”處理。<br>
<br>
13.12.4 CardLayout<br>
CardLayout允許我們在更復雜的擁有真正的文件夾卡片與一條邊相遇的環(huán)境里創(chuàng)建大致相同于“卡片式對話框”的布局,我們必須壓下一個卡片使不同的對話框帶到前面來。在AWT里不是這樣的:CardLayout是簡單的空的空格,我們可以自由地把新卡片帶到前面來。(JFC/Swing庫包括卡片式的窗格看起來非常的棒,且可以我們處理所有的細節(jié)。)<br>
<br>
1. 聯(lián)合布局(Combining layouts)<br>
下面的例子聯(lián)合了更多的布局類型,在最初只有一個布局管理器被程序片或應用程序操作看起來相當?shù)睦щy。這是事實,但如果我們創(chuàng)建更多的面板對象,每個面板都能擁有一個布局管理器,并且像被集成到程序片或應用程序中一樣使用程序片或應用程序的布局管理器。這就象下面程序中的一樣給了我們更多的靈活性:<br>
<br>
616-617頁程序<br>
<br>
這個例子首先會創(chuàng)建一種新類型的面板:BottonPanel(按鈕面板)。它包括一個單獨的按鈕,安放在BorderLayout的中央,那意味著它將充滿整個的面板。按鈕上的標簽將讓我們知道我們在CardLayout上的那個面板上。<br>
在程序片里,面板卡片上將存放卡片和布局管理器CL因為CardLayout必須組成類,因為當我們需要處理卡片時我們需要訪問這些句柄。<br>
這個程序片變成使用BorderLayout來取代它的默認FlowLayout,創(chuàng)建面板來容納三個按鈕(使用FlowLayout),并且這個面板安置在程序片末尾的“North”。卡片面板增加到程序片的“Center”里,有效地占據(jù)面板的其余地方。<br>
當我們增加BottonPanels(或者任何其它我們想要的組件)到卡片面板時,add()方法的第一個自變量不是“North”,“South”等等。相反的是,它是一個描述卡片的字符串。如果我們想輕擊那張卡片使用字符串,我們就可以使用,雖然這字符串不會顯示在卡片的任何地方。使用的方法不是使用action();代之使用first()、next()和last()等方法。請查看我們有關其它方法的文件。<br>
在Java中,使用的一些卡片式面板結構十分的重要,因為(我們將在后面看到)在程序片編程中使用的彈出式對話框是十分令人沮喪的。對于Java
1.0版的程序片而言,CardLayout是唯一有效的取得很多不同的“彈出式”的窗體。<br>
<br>
13.12.5 GridBagLayout<br>
很早以前,人們相信所有的恒星、行星、太陽及月亮都圍繞地球公轉。這是直觀的觀察。但后來天文學家變得更加的精明,他們開始跟蹤個別星體的移動,它們中的一些似乎有時在軌道上緩慢運行。因為天文學家知道所有的天體都圍繞地球公轉,天文學家花費了大量的時間來討論相關的方程式和理論去解釋天體對象的運行。當我們試圖用GridBagLayout來工作時,我們可以想像自己為一個早期的天文學家。基礎的條例是(公告:有趣的是設計者居然在太陽上(這可能是在天體圖中標錯了位置所致,譯者注))所有的天體都將遵守規(guī)則來運行。哥白尼日新說(又一次不顧嘲諷,發(fā)現(xiàn)太陽系內的所有的行星圍繞太陽公轉。)是使用網絡圖來判斷布局,這種方法使得程序員的工作變得簡單。直到這些增加到Java里,我們忍耐(持續(xù)的冷嘲熱諷)西班牙的GridBagLayout和GridBagConstraints狂熱宗教。我們建議廢止GridBagLayout。取代它的是,使用其它的布局管理器和特殊的在單個程序里聯(lián)合幾個面板使用不同的布局管理器的技術。我們的程序片看起來不會有什么不同;至少不足以調整GridBagLayout限制的麻煩。對我而言,通過一個例子來討論它實在是令人頭痛(并且我不鼓勵這種庫設計)。相反,我建議您從閱讀Cornell和Horstmann撰寫的《核心Java》(第二版,Prentice-Hall出版社,1997年)開始。<br>
在這范圍內還有其它的:在JFC/Swing庫里有一個新的使用Smalltalk的受人歡迎的“Spring
and Struts”布局管理器并且它能顯著地減少GridBagLayout的需要。<br>
<br>
13.13 action的替代品<br>
正如早先指出的那樣,action()并不是我們對所有事進行分類后自動為handleEvent()調用的唯一方法。有三個其它的被調用的方法集,如果我們想捕捉某些類型的事件(鍵盤、鼠標和焦點事件),因此我們不得不過載規(guī)定的方法。這些方法是定義在基礎類組件里,所以他們幾乎在所有我們可能安放在窗體中的組件中都是有用的。然而,我們也注意到這種方法在Java
1.1版中是不被支持的,同樣盡管我們可能注意到繼承代碼利用了這種方法,我們將會使用Java
1.1版的方法來代替(本章后面有詳細介紹)。<br>
<br>
組件方法 何時調用<br>
<br>
action(Event evt, Object what)
當?shù)湫偷氖录槍M件發(fā)生(例如,當按下一個按鈕或下拉列表項目被選中)時調用<br>
keyDown(Event evt, int key)
當按鍵被按下,組件擁有焦點時調用。第二個自變量是按下的鍵并且是冗余的是從evt.key處復制來的<br>
keyup(Event evt, int key) 當按鍵被釋放,組件擁有焦點時調用<br>
lostFocus(Event evt, Object what) 焦點從目標處移開時調用。通常,what是從evt.arg里冗余復制的<br>
gotFocus(Event evt, Object what) 焦點移動到目標時調用<br>
mouseDown(Event evt, int x,int y) 一個鼠標按下存在于組件之上,在X,Y座標處時調用<br>
mouseUp(Event evt, int x, int y) 一個鼠標升起存在于組件之上時調用<br>
mouseMove(Event evt, int x, int y) 當鼠標在組件上移動時調用<br>
mouseDrag(Event evt, int x, int y) 鼠標在一次mouseDown事件發(fā)生后拖動。所有拖動事件都會報告給內部發(fā)生了mouseDown事件的那個組件,直到遇到一次mouseUp為止<br>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -