首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 6 全新模態對話框 API 深度解析

     編輯:Java 相關知識

前言

對話框是擁有標題與邊框的頂層彈出視窗,常用於接收用戶輸入。在 JDK 5.0 及更早版本中,建立對話框時必須指定一個框架視窗或另一個對話框作為其擁有者,即使該視窗不可見。當擁有者視窗最小化時,對話框會自動隱藏;擁有者恢復時,對話框隨之重現。

對話框分為模態與非模態兩種。模態對話框會阻擋除其擁有者視窗外的所有其他頂層視窗輸入,並捕獲焦點直到關閉(通常響應按鈕點擊)。非模態對話框則允許用戶在其他視窗仍可獲取焦點時改變其狀態,常用於工具欄視窗,如圖像編輯程式中的面板。

舊版模態模型存在諸多限制與問題,最著名的是 JavaHelp 工具視窗無法與模態對話框(如標準「另存為」對話框)同時互動。Java 6(代號 Mustang)透過全新的抽象視窗工具箱(AWT)模態模型徹底解決了這些問題。新模型允許開發者根據所選模態類型指定對話框模態阻擋的範圍,並支援真正無父視窗(null 父視窗)的視窗與對話框,有助於限制作用域與模態範圍。

四大模態類型

Java 6 支援四種模態類型,按阻擋強度遞增排序:

  • 無模態:可見時不阻擋任何其他視窗。
  • 文檔模態:阻擋同一文檔內所有視窗(除其子層級視窗)。文檔指共享同一根視窗的視窗層級結構(框架、對話框等),文檔根視窗為無擁有者的最頂層視窗。
  • 應用程式模態:阻擋同一應用程式內所有視窗(除其子層級視窗)。多個 Applet 在瀏覽器中可能被視為獨立應用程式或單一應用程式,視具體實現環境而定。
  • 工具箱模態:阻擋同一工具箱中運行的所有視窗(除其子層級視窗)。多個 Applet 共享同一工具箱,因此某 Applet 顯示的工具箱模態對話框可能影響其他 Applet。

預設情況下對話框為無模態;在 Mustang 中建構模態對話框預設使用應用程式模態。模態優先權反映阻擋範圍的巢狀關係:無模態(空範圍)→ 文檔模態(特定應用程式內)→ 應用程式模態(整個應用程式)→ 工具箱模態(整個工具箱)。需注意新模型未實現系統模態(阻擋桌面上所有應用程式)。

新建構器詳解

為實現真正無父視窗且保持向後相容,AWT 團隊引入了新建構器。JDK 5.0 允許傳遞 null 作為 JDialog/JWindow 父視窗,實際上會建立一個不可見的共享擁有者框架視窗。Java SE 6 引入文檔模態對話框後,工具箱能識別真正無父視窗的對話框/視窗。

Mustang 仍允許向舊版建構器傳遞 null(行為不變,保證相容),但新增 Dialog/Window 及 JDialog/JWindow 建構器可接受 null 並建立真正無父視窗的對話框。常用建構器包括:

  • JDialog(Dialog owner):建立無標題、指定對話框為父視窗的非模態對話框
  • JDialog(Dialog owner, boolean modal):指定擁有者與模態
  • JDialog(Dialog owner, String title):指定標題與擁有者的非模態對話框
  • JDialog(Dialog owner, String title, boolean modal):指定標題、模態與擁有者
  • JDialog(Dialog owner, String title, boolean modal, GraphicsConfiguration gc):完整參數建構
  • JDialog(Frame owner):指定框架為擁有者的非模態對話框
  • JDialog(Window owner, String title, Dialog.ModalityType modalityType):關鍵新增,支援指定模態類型(如 DOCUMENT_MODAL、APPLICATION_MODAL 等)

與擁有者視窗協作

使用新模態模型時需注意:

  • 無擁有者的文檔模態對話框:Dialog 繼承自 Window,無擁有者時自動成為文檔根視窗,其阻擋範圍為空,行為等同非模態。
  • 應用程式/工具箱模態對話框的擁有者影響:阻擋範圍不依賴擁有者,擁有者僅影響 Z-Order(頂層組件相對順序)。對話框永遠位於其擁有者上方。
  • 執行時期改變模態類型:對可見對話框修改模態類型無即時效果,需隱藏後重新顯示才生效。

程式碼範例與示意圖

以下示範新模態 API 應用,包含 java.awt.Dialog.ModalExclusionType 與 java.awt.Dialog.ModalityType 的靈活運用:

圖1: 對話框的模態優先權

圖1:對話框的模態優先權

圖2: 被阻擋與未被阻擋的對話框

圖2:被阻擋與未被阻擋的對話框

關鍵程式碼片段:

// 設定 DOCUMENT_MODAL 對話框
d22.setBounds(sw - 500 + 32, 232, 300, 200);
d22.addWindowListener(closeWindow);
d22.setLayout(new BorderLayout());
Label l = new Label("DOCUMENT_MODAL");
l.setBackground(Color.BLUE);
l.setAlignment(Label.CENTER);
l.setFont(labelFont);
d22.add(l, BorderLayout.CENTER);

// 排除模態的框架視窗
Frame f3 = new Frame("Excluded Frame");
f3.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
// ... 設定位置、監聽器、標籤與按鈕 ...
f3.setVisible(true);

// 檔案對話框(向後相容,預設 APPLICATION_MODAL)
FileDialog fd4 = new FileDialog(f4, "File Dialog", FileDialog.LOAD);
fd4.setBounds(sw - 400 + 32, sh - 300 + 32, 300, 200);

AWT 特性與注意事項

永遠置頂視窗衝突

當非置頂的模態對話框阻擋置頂視窗時,Z-Order 未明確定義且平台相依。解決方案:將對話框亦設為置頂(d.setAlwaysOnTop(true))。

toFront()/toBack() 行為

模態對話框應永遠位於被阻擋視窗上方。被阻擋視窗移至前景時,其阻擋對話框會隨之移至前景並置於上方;模態對話框移至背景時,所有被阻擋視窗亦會移至背景。

最小化/最大化/關閉被阻擋視窗

用戶通常無法互動式最小化/最大化/關閉被阻擋視窗(平台相依),但可透過程式呼叫 setVisible(false) 或 dispose() 關閉。

激活被阻擋視窗

選擇被阻擋視窗時,可能連同阻擋對話框一起移至前景並成為活動視窗(平台相依)。

隱藏模態對話框

擁有焦點的模態對話框隱藏時,其擁有者可能成為活動視窗(平台相依);無焦點時活動視窗保持不變。

安全性權限

顯示工具箱模態對話框需 AWTPermission "toolkitModality",防止 Applet 對話框阻擋瀏覽器/JWS 視窗。同樣權限用於從工具箱模態排除視窗。

平台支援檢查

使用 Toolkit.isModalityTypeSupported(modalityType) 與 Toolkit.isModalExclusionTypeSupported(modalExclusionType) 檢查平台支援度。不支援時模態對話框表現為非模態,排除標記無效果。

相容性說明

預設模態類型為應用程式模態(Dialog.setModal(true)、Dialog(owner, true) 等 API 使用)。JDK 6 前預設為工具箱模態,兩者差異僅在於 JWS 啟動的 Applet 與應用程式互動行為。所有 Java SE 平台 API 變更須經 JSR 270 專家組審核同意。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved