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

Swing 內部視窗(JInternalFrame)與桌面面板(JDesktopPane)實戰教學

     編輯:Java 程式設計入門

在 Java Swing 開發中,構建類似 IDE(整合開發環境)那樣擁有「視窗中視窗」效果的多文檔介面(MDI),核心在於 JInternalFrame(內部視窗) 與 JDesktopPane(桌面面板) 的搭配使用。本文將透過完整程式碼範例,詳細解析如何正確建立、佈局與定位內部視窗,並解決新手常遇到的「視窗不顯示」或「大小異常」等棘手問題。

核心元件架構圖解

  • JDesktopPane:繼承自 JLayeredPane,是容納內部視窗的特殊容器,負責管理 Z 軸層疊順序與拖曳行為。
  • JInternalFrame:可調整大小、關閉、最大化、最小化、圖示化的輕量級視窗,必須加入 JDesktopPane 才能正常運作。
  • JFrame:最外層的主視窗,其 Content Pane 通常設為 BorderLayout,中央放置 JDesktopPane。

完整可執行範例程式碼

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class InternalFrameDemo extends JFrame {

    public InternalFrameDemo() {
        initUI();
    }

    private void initUI() {
        setTitle("MDI 內部視窗範例");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        // 1. 建立桌面面板 (容器)
        JDesktopPane desktop = new JDesktopPane();
        // 設定桌面背景顏色,方便觀察範圍
        desktop.setBackground(Color.LIGHT_GRAY); 
        
        // 2. 建立第一個內部視窗
        JInternalFrame frame1 = createInternalFrame("內部視窗 A", 50, 50, 300, 200);
        frame1.add(new JLabel("我是視窗 A 的內容", SwingConstants.CENTER));
        desktop.add(frame1);
        
        // 3. 建立第二個內部視窗
        JInternalFrame frame2 = createInternalFrame("內部視窗 B", 100, 100, 300, 200);
        JPanel panel = new JPanel(new BorderLayout());
        panel.add(new JLabel("視窗 B 頂部資訊", SwingConstants.CENTER), BorderLayout.NORTH);
        panel.add(new JButton("互動按鈕"), BorderLayout.CENTER);
        frame2.add(panel);
        desktop.add(frame2);
        
        // 4. 將桌面面板置於主視窗中央
        add(desktop, BorderLayout.CENTER);
        
        // 5. 視窗定位與顯示 (關鍵步驟)
        pack(); // 依據元件優先尺寸調整主視窗
        centerOnScreen(); // 置中螢幕
        setVisible(true);
    }
    
    /** 封裝建立內部視窗的邏輯 */
    private JInternalFrame createInternalFrame(String title, int x, int y, int w, int h) {
        JInternalFrame iframe = new JInternalFrame(title, 
            true,  // resizable 可調整大小
            true,  // closable 可關閉
            true,  // maximizable 可最大化
            true   // iconifiable 可最小化
        );
        iframe.setBounds(x, y, w, h); // 設定位置與大小 (比 setSize+setLocation 更佳)
        iframe.setVisible(true); // 【關鍵】必須顯式設為 true,否則不會顯示!
        return iframe;
    }
    
    /** 將主視窗置中於螢幕 */
    private void centerOnScreen() {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = getSize();
        if (frameSize.height > screenSize.height) frameSize.height = screenSize.height;
        if (frameSize.width > screenSize.width) frameSize.width = screenSize.width;
        setLocation((screenSize.width - frameSize.width) / 2, 
                    (screenSize.height - frameSize.height) / 2);
    }

    public static void main(String[] args) {
        // 確保在 EDT (事件派發執行緒) 中啟動 Swing 程式
        SwingUtilities.invokeLater(() -> new InternalFrameDemo());
    }
}

四大新手必踩雷點與解決方案

1. 忘記呼叫 setVisible(true)

現象: 程式碼編譯通過,主視窗出現,但桌面面板一片空白,內部視窗消失無蹤。
原因: JInternalFrame 預設不可見,不同於 JFrame 或 JDialog,必須手動呼叫 iframe.setVisible(true)。
對策: 在加入桌面面板前,務必加上這行代碼。

2. 直接將 InternalFrame 加入 JFrame 而非 JDesktopPane

現象: 視窗出現但無法拖曳、無法最大化、標題列渲染異常。
原因: JInternalFrame 依賴 DesktopManager 管理行為,只有 JDesktopPane 提供此管理器。
對策: 永遠 desktop.add(internalFrame),不要 frame.add(internalFrame)。

3. 使用 setSize() 卻發現視窗大小不對

現象: 設定 setSize(300, 200),但實際顯示比預期小,標題列被切掉一部分。
原因: setSize 設定的是視窗「客戶區」大小,不含標題列與邊框;且在某些 Look & Feel 下計算差異大。
對策: 使用 setBounds(x, y, width, height) 一次設定位置與外部尺寸,或呼叫 pack() 讓佈局管理器自動計算優先尺寸。

4. 主視窗未呼叫 pack() 就 setVisible(true)

現象: 主視窗極小,只看到標題列,內容區塊被壓縮。
原因: JFrame 預設大小為 0x0。若先 setVisible(true) 再 pack(),會導致畫面閃爍或內部視窗渲染異常。
對策: 標準流程:add元件 → pack() → centerOnScreen() → setVisible(true)。

進階技巧:動態管理內部視窗

// 取得桌面上所有內部視窗
JInternalFrame[] frames = desktop.getAllFrames();

// 遍歷關閉所有視窗 (需捕獲 PropertyVetoException)
for (JInternalFrame f : frames) {
    try { f.setClosed(true); } 
    catch (PropertyVetoException e) { e.printStackTrace(); }
}

// 監聽內部視窗事件 (關閉、圖示化、激活等)
frame1.addInternalFrameListener(new InternalFrameAdapter() {
    @Override
    public void internalFrameClosing(InternalFrameEvent e) {
        System.out.println("視窗即將關閉,可在此儲存資料");
    }
});

總結

掌握 JDesktopPane + JInternalFrame 的正確使用姿勢,關鍵在於三個動作:**容器正確、顯式可見、尺寸定位**。避開上述四大坑點,您就能輕鬆構建出專業級的多文檔介面應用程式。雖然現代趨勢偏向單視窗多標籤頁(如 IDEA、VS Code),但 MDI 架構在特定垂直領域(如監控儀表板、金融交易終端)依然有其不可替代的價值。

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