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

深度解析 Java 6 新模態對話框 API:Modality Types 與 ModalExclusion

     編輯:Java 相關知識

背景:舊模態模型的痛點

JDK 5.0 以前,模態對話框僅支援「應用程式級」阻塞,導致 JavaHelp 視窗、Splash Screen 等輔助視窗被錯誤阻塞。Java 6 (Mustang) 引入分層模態模型,精確控制阻塞範圍。

四大模態類型

模態類型常數阻塞範圍典型用途
無模態ModalityType.MODELESS不阻塞任何視窗工具列、屬性面板、聊天視窗
文件模態ModalityType.DOCUMENT_MODAL同一文件根視窗下的所有視窗 (除子層級)單文件編輯器的對話框、另存新檔
應用程式模態ModalityType.APPLICATION_MODAL同一應用程式所有視窗 (除子層級)登入框、關鍵設定、JDK 6+ 預設 setModal(true)
工具箱模態ModalityType.TOOLKIT_MODAL同一 Toolkit 所有視窗 (跨 Applet)極少用,需 AWTPermission("toolkitModality")

優先序:MODELESS < DOCUMENT_MODAL < APPLICATION_MODAL < TOOLKIT_MODAL。高優先序可阻塞低優先序視窗。

新建構子與關鍵 API


// 核心新建構子 (JDialog 為例)
public JDialog(Window owner, String title, ModalityType modalityType);
public JDialog(Window owner, String title, ModalityType modalityType, GraphicsConfiguration gc);

// 靜態工廠 (Java 8+ 常用)
JDialog dialog = new JDialog((Window) null, "標題", ModalityType.DOCUMENT_MODAL);

// 模態排除:讓視窗不被特定模態阻塞
frame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);

ModalExclusionType 三種:

  • NO_EXCLUDE (預設)
  • APPLICATION_EXCLUDE:不被 APPLICATION_MODAL 阻塞
  • TOOLKIT_EXCLUDE:不被 TOOLKIT_MODAL 阻塞 (需權限)

真正的無擁有者視窗

JDK 6 前傳 null 給 JDialog 會隱式建立共享隱形 Frame。JDK 6 起 new JDialog((Window)null, ...) 真正建立無擁有者視窗,配合 DOCUMENT_MODAL 可實現「僅阻塞同文件群」語意。

Z-Order 與 Always-On-Top 互動規則

  • 模態對話框永遠置於其阻塞視窗之上
  • setAlwaysOnTop(true) 與模態衝突時,行為為平台相依
  • 解決方案:對話框同樣設定 setAlwaysOnTop(true)

平台支援檢查


Toolkit tk = Toolkit.getDefaultToolkit();
if (tk.isModalityTypeSupported(ModalityType.DOCUMENT_MODAL)) {
    // 安全使用
} else {
    // 降級為 MODELESS
}

完整範例:多文件編輯器模擬


import java.awt.*;
import java.awt.event.*;

public class ModalityDemo {
    public static void main(String[] args) {
        // 文件 1:紅色 Frame + 無模態對話框 + 文件模態對話框
        Frame doc1 = new Frame("文件 1");
        doc1.setBackground(Color.RED);
        doc1.setBounds(50, 50, 300, 200);
        doc1.setVisible(true);

        Dialog d11 = new Dialog(doc1, "無模態", ModalityType.MODELESS);
        d11.setBounds(100, 100, 200, 100);
        d11.setVisible(true);

        Dialog d12 = new Dialog(doc1, "文件模態", ModalityType.DOCUMENT_MODAL);
        d12.setBounds(350, 100, 200, 100);
        d12.setVisible(true); // 僅阻塞 doc1 及其子視窗

        // 文件 2:藍色 Frame
        Frame doc2 = new Frame("文件 2");
        doc2.setBackground(Color.BLUE);
        doc2.setBounds(50, 300, 300, 200);
        doc2.setVisible(true); // 不被 d12 阻塞

        // 排除框架:綠色,不被應用程式模態阻塞
        Frame excluded = new Frame("排除框架");
        excluded.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
        excluded.setBounds(400, 300, 200, 150);
        excluded.setVisible(true);

        // 應用程式模態檔案對話框 (預設 APPLICATION_MODAL)
        FileDialog fd = new FileDialog(doc1, "開啟檔案", FileDialog.LOAD);
        fd.setVisible(true); // 阻塞 doc1、doc2,但不阻塞 excluded
    }
}

相容性與遷移建議

  • Dialog.setModal(true) 現在對應 APPLICATION_MODAL (舊版為 TOOLKIT_MODAL),行為差異僅在多 Applet/ JWS 場景。
  • 舊建構子 new JDialog(frame, true) 保持相容。
  • 新程式碼明確指定 ModalityType,避免隱含語意。

安全性注意

使用 TOOLKIT_MODAL 或 TOOLKIT_EXCLUDE 需 AWTPermission("toolkitModality"),防止不受信 Applet 阻塞瀏覽器/JWS 視窗。

結語

Java 6 模態 API 以「文件/應用程式/工具箱」三層語意取代單一布林旗標,配合 ModalExclusionType 精準控制視窗互動。現代 Swing/JavaFX 專案應善用此機制,提升多視窗應用的使用者體驗。

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