一、 引言
模態一直是我最喜歡的話題之一,至少因為一直存在大量的感興趣的客戶的有關於這方面內容的回饋資訊。作為一個Java SE測試工程師,這正是驅動我工作的動力-它使我一直處於忙碌之中,而且還為我的工作帶來快樂。另一方面,這也說明了模態是用戶端最廣為使用的特徵之一,不管是使用Swing還是使用AWT進行開發。
在Java SE 6(代碼名為Mustang)中,我的工作變得更有意思——在模態方面進行大量的改進。這些改進將為應用程式開發人員提供更大的靈活性——在設計可能用到模態對話方塊行為的程式的過程中。在深入討論這些改進之前,讓我們首先看一下在Mustang之前的AWT所提供的功能。
從其有關介紹來看,AWT僅提供了兩種類型的模態:模態和非模態的。
·模態-顯示任何一個模態視窗時,應用程式中的所有視窗都將被阻斷。
·非模態的-這是一種不能阻斷任何視窗的對話方塊。
我們可能會提出下列一些有趣的問題:
·為什麼一個模態對話方塊應該阻斷當前應用程式中的所有的視窗?
·如果模態對話方塊僅阻斷父視窗而不是其它視窗,不好嗎?
·由應用程式開發人員來決定(代替AWT)在他的應用程式的對話方塊應該阻斷什麼視窗,不好嗎?比方說,當一個模態對話方塊處於活動狀態時,如果一個應用程式使用者想要滾動說明視窗來看一下他/她在對話方塊中作了怎樣的選擇,他/她該如何?這一點呢?
AWT在新的Java SE 6中加強了這一方面的功能。現在,它提供了四種類型的模態(應用範圍由寬到窄):工具箱,應用程式,文檔和非模態的。開發人員可以視具體需要為他的對話方塊選擇適當的模態類型。
二、 工具箱模態
選擇這種類型,如果:
·你的對話方塊必須阻斷你的應用程式中的所有視窗(除了該對話方塊的子層次視窗之外)
·你的對話方塊應該阻斷你的applet及同一個工具箱中所有其它applet
·你的對話方塊應該阻斷瀏覽器本身
·你想使用一個具有最大阻斷範圍的對話方塊
三、 應用程式模態
就通常應用程式來說,在應用程式和工具箱模態之間並不存在很多區別。但是,如果你正在開發一個applet,那麼搞清其區別是十分重要的。
·如果在瀏覽器中啟動若干applet,那麼,根據你使用的是什麼瀏覽器(檢查你的瀏覽器文檔),它們可以被當作單獨的應用程式或單個的應用程式。應用程式模態對話方塊將阻斷同一個"應用程式"中的所有的視窗
·預設的模態類型,未給模態對話方塊指定任何內容時使用。
四、 文檔模態
選擇這種類型,如果:
·對話方塊只阻斷同一個文檔中的視窗("文檔"由最接近頂部的沒有所有者的視窗決定)
·對話方塊應該具有鄰近非模態的視窗的最小範圍的阻斷。
五、 非模態型
如果你不想要你的對話方塊阻斷任何視窗,那麼你可以使用這種模態。
注意 既然工具箱模態對話方塊能夠阻斷瀏覽器/Java WebStart,那麼你需要一個AWTPermission "toolkitModality"以便從一個applet中使用這種類型的模態。
總的而言,在選擇每一個對話方塊的適當模態類型(根據它應該阻斷應用程式中的其它最上層視窗的指定範圍)時,這為應用程式開發人員提供大量的靈活性。
六、 模態排除
還有另外一種場所-在你的應用程式中存在許多視窗,並且你想要你的模態對話方塊阻斷除了一個視窗之外的所有其它視窗。在這樣情況下,你將必須選擇模態類型-它具有最大範圍的阻斷能力。但是,從被對話方塊阻斷的視窗中排除這些不應該被阻斷的視窗,有可能嗎?是的,完全可以!
下面,讓我們看一下AWT在這一方面所提供的功能:
在Java SE 6中,AWT又引入了兩種模態排除類型(參考圖1)。
(一) 阻斷工具箱模態對話方塊排除型
如果一個視窗是工具箱模態排除的,那麼它就不會被任何應用程式或工具箱模態對話方塊所阻斷。另外,它也不會被文檔模態對話方塊從其它的子層次視窗(注意:如果你使用的是一種applet環境,那麼你會要求AWTPermission-"toolkitModality"使用這種排除類型)外所阻斷。
(二) 阻斷應用程式模態對話方塊排除型
如果一個視窗是一個應用程式模態排除的,那麼它就不會被任何應用程式模態對話方塊所阻斷。另外,它也不會被文檔模態對話方塊從其子層次視窗外面所阻斷。
預設情況下,一個視窗的模態排除屬性是被關閉的。也就是說,預設情況下,它被阻斷-如果它在可見的任何模態對話方塊的阻斷範圍之內。
在使用任何模態或排除類型之前,請檢查一下是否你的平台支援這種類型-通過調用由java.awt.Toolkit類所提供方法isModalitySupported()和isModalExclusionTypeSupported()來實現。
七、 無父對話方塊
一直以來,對話方塊總是有一個父視窗與之相關聯。但是,一個對話方塊總是有一個父視窗真正非常有必要嗎?答案不再是這樣了!
現在,在Java SE 6中,我們有可能建立一個父視窗為"null"的AWT對話方塊(在對話方塊構造器中的"parent"參數值為null)。在以前的發行版本中,這一直會引發一個異常。
因此,如果你不想讓你的對話方塊有一個父視窗的話,那麼你就不再需要建立一個"啞元"父視窗了!
除此之外,還有一些有趣的值得探討的內容:
(一) 如果無父對話方塊是文檔模態的
一個沒有所有者的文檔模態對話方塊會自動地成為該文檔的一個根,因此它的阻斷範圍為空白。因此,它的行為就象一個非模態的對話方塊一樣。
(二) 如果無父對話方塊是應用程式或工具箱模態
一個應用程式或工具箱模態對話方塊(相對於一個文檔模態對話方塊)的阻斷範圍並不依賴於它的所有者,因此對阻斷範圍不會產生任何影響。
在任何情況下,一個模態對話方塊應該總是位於它阻斷的其它最上層視窗的頂部。你不能改變一個已經可見的對話方塊的模態類型。如果你想這樣做,那麼你需要隱藏它並且再次顯示之,以便該新指定的模態類型起作用。