在 Java 桌面應用開發中,JOptionPane 是最常用的模態對話框工具類,提供了七種預置對話框類型,涵蓋信息提示、確認選擇、輸入獲取等常見交互場景。本文系統整理 JOptionPane 核心 API、圖標常量、按鈕配置、輸入驗證與自定義對話框擴展技巧。
| 方法 | 用途 | 返回值 | 典型場景 |
|---|---|---|---|
showMessageDialog |
純信息提示 (僅確定按鈕) | void | 操作成功、錯誤提示、警告通知 |
showConfirmDialog |
確認選擇 (是/否/取消) | int (YES/NO/CANCEL/OK/CLOSED_OPTION) | 刪除確認、保存確認、退出確認 |
showInputDialog |
獲取用戶輸入 (文本/下拉選擇) | String / Object | 輸入姓名、選擇項目、密碼輸入 |
showOptionDialog |
完全自定義按鈕/圖標/選項 | int (用戶選擇的選項索引) | 複雜選擇、自定義按鈕文本、多圖標 |
showInternalMessageDialog |
內部框架版 (JDesktopPane 專用) | void | MDI 多文檔界面應用 |
showInternalConfirmDialog |
內部框架確認對話框 | int | MDI 環境下確認操作 |
showInternalOptionDialog |
內部框架選項對話框 | int | MDI 環境下自定義選項 |
// 圖標類型常量 (影響對話框左側圖標)
JOptionPane.ERROR_MESSAGE // 紅色叉號 - 錯誤
JOptionPane.INFORMATION_MESSAGE // 藍色 i - 信息
JOptionPane.WARNING_MESSAGE // 黃色三角形 - 警告
JOptionPane.QUESTION_MESSAGE // 問號 - 詢問
JOptionPane.PLAIN_MESSAGE // 無圖標 - 純文本
// 按鈕選項常量
DEFAULT_OPTION // 單個 "OK" 按鈕
YES_NO_OPTION // "Yes" / "No"
YES_NO_CANCEL_OPTION // "Yes" / "No" / "Cancel"
OK_CANCEL_OPTION // "OK" / "Cancel"
// 簡單信息
JOptionPane.showMessageDialog(null, "數據保存成功!", "提示", JOptionPane.INFORMATION_MESSAGE);
// 錯誤提示
JOptionPane.showMessageDialog(parentFrame,
"數據庫連接失敗:\n" + e.getMessage(),
"錯誤", JOptionPane.ERROR_MESSAGE);
// 警告提示
JOptionPane.showMessageDialog(null,
"該操作不可逆,請確認後繼續!",
"警告", JOptionPane.WARNING_MESSAGE);
// 是/否 確認
int result = JOptionPane.showConfirmDialog(
parentFrame,
"確定要刪除這條記錄嗎?",
"刪除確認",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (result == JOptionPane.YES_OPTION) {
deleteRecord();
} else if (result == JOptionPane.NO_OPTION || result == JOptionPane.CLOSED_OPTION) {
// 用戶點擊 No 或關閉窗口
}
// 是/否/取消 三選項
int result2 = JOptionPane.showConfirmDialog(
null, "是否保存修改?", "保存確認",
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
switch (result2) {
case JOptionPane.YES_OPTION: saveAndExit(); break;
case JOptionPane.NO_OPTION: exitWithoutSave(); break;
case JOptionPane.CANCEL_OPTION: return; // 繼續編輯
case JOptionPane.CLOSED_OPTION: return; // 關閉窗口同取消
}
// 簡單文本輸入
String name = JOptionPane.showInputDialog("請輸入您的姓名:");
if (name != null && !name.trim().isEmpty()) {
System.out.println("你好, " + name);
} else if (name == null) {
// 用戶點擊取消或關閉
}
// 帶默認值和下拉選擇
Object[] options = {"管理員", "操作員", "訪客"};
Object selection = JOptionPane.showInputDialog(
null, "選擇角色:", "角色選擇",
JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
if (selection != null) {
System.out.println("選擇角色: " + selection);
}
// 密碼輸入 (需自定義組件)
JPasswordField passwordField = new JPasswordField();
Object[] msg = {"請輸入密碼:", passwordField};
int result = JOptionPane.showConfirmDialog(null, msg, "密碼驗證",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
String pwd = new String(passwordField.getPassword());
// 驗證密碼...
}
Object[] options = {"立即更新", "稍後提醒", "跳過此版本"};
int choice = JOptionPane.showOptionDialog(
parentFrame,
"發現新版本 v2.0.1,是否更新?",
"軟件更新",
JOptionPane.DEFAULT_OPTION,
JOptionPane.INFORMATION_MESSAGE,
null, // 使用默認圖標
options,
options[0] // 默認選中第一個
);
switch (choice) {
case 0: startUpdate(); break;
case 1: scheduleReminder(); break;
case 2: skipVersion(); break;
case JOptionPane.CLOSED_OPTION: break; // 關閉窗口
}
// null = 居中顯示在屏幕中央
// parentFrame = 居中顯示在父窗口中央 (推薦,體驗更好)
JOptionPane.showMessageDialog(parentFrame, "內容", "標題", JOptionPane.INFORMATION_MESSAGE);
// 換行符
JOptionPane.showMessageDialog(null, "第一行\n第二行\n第三行", "多行", JOptionPane.INFORMATION_MESSAGE);
// HTML 富文本 (支援基本標籤)
String html = "粗體 紅色
換行";
JOptionPane.showMessageDialog(null, html, "HTML", JOptionPane.INFORMATION_MESSAGE);
ImageIcon icon = new ImageIcon(getClass().getResource("/icons/custom.png"));
JOptionPane.showMessageDialog(null, "自定義圖標", "標題", JOptionPane.PLAIN_MESSAGE, icon);
// 長時間任務中的進度提示
JOptionPane pane = new JOptionPane("處理中...", JOptionPane.INFORMATION_MESSAGE);
JDialog dialog = pane.createDialog(parentFrame, "處理進度");
new SwingWorker<Void, Void>() {
@Override protected Void doInBackground() {
// 後台耗時任務
return null;
}
@Override protected void done() {
dialog.dispose(); // 關閉對話框
}
}.execute();
dialog.setVisible(true); // 模態阻塞直到任務完成
String input;
while (true) {
input = JOptionPane.showInputDialog(null, "請輸入郵箱:", "輸入", JOptionPane.QUESTION_MESSAGE);
if (input == null) return; // 取消
if (input.matches("^[\\w.-]+@[\\w.-]+\\.\\w+$")) break;
JOptionPane.showMessageDialog(null, "郵箱格式不正確,請重新輸入", "錯誤", JOptionPane.ERROR_MESSAGE);
}
| 問題 | 原因 | 解決 |
|---|---|---|
| 對話框顯示位置錯亂 | 父組件為 null 或未實現 | 傳入有效的 JFrame/JDialog 實例 |
| 中文顯示方塊/亂碼 | 字體不支援中文 | 設置全局字體 UIManager.put("OptionPane.messageFont", new Font("微軟雅黑", Font.PLAIN, 14)) |
| showInputDialog 返回 null | 用戶點擊取消/關閉 | 必須判斷 null 再使用 |
| 模態對話框阻塞 EDT 導致界面凍結 | 在事件分發線程執行耗時操作 | 耗時操作放 SwingWorker,對話框僅作提示 |
| 自定義組件大小不適應 | 組件首選大小未設置 | 組件.setPreferredSize(new Dimension(300, 100)) |
JOptionPane 作為 Swing 內置的模態對話框工具箱,通過七大靜態方法覆蓋了 90% 的桌面交互需求。核心掌握點:選對方法類型 → 設置正確圖標/按鈕選項 → 傳入有效父組件 → 處理返回值 (含 CLOSED_OPTION) → 異步操作配合 SwingWorker。對於複雜交互需求,可繼承 JDialog 實現完全自定義對話框,或引入第三方庫 (如 FlatLaf、Jide、Material UI) 獲得現代化外觀體驗。