Swing 通過 JDesktopPane(桌面容器)管理多個 JInternalFrame(內部窗體),實現類似 Windows 多文檔界面:
OUTLINE_DRAG_MODE),提升性能import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class InternalFrameDemo extends JFrame implements ActionListener {
private JDesktopPane desktop;
public InternalFrameDemo() {
super("InternalFrameDemo");
// 窗體佔據螢幕大部,四周留 50px 邊距
int inset = 50;
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(inset, inset, screen.width - inset * 2, screen.height - inset * 2);
desktop = new JDesktopPane();
createFrame(); // 創建首個內部窗體
setContentPane(desktop);
setJMenuBar(createMenuBar());
// 拖拽時僅顯示輪廓,減少重繪開銷
desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
}
private JMenuBar createMenuBar() {
JMenuBar bar = new JMenuBar();
JMenu fileMenu = new JMenu("文件");
fileMenu.setMnemonic(KeyEvent.VK_D);
JMenuItem newItem = new JMenuItem("新文檔");
newItem.setMnemonic(KeyEvent.VK_N);
newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.ALT_MASK));
newItem.setActionCommand("new");
newItem.addActionListener(this);
fileMenu.add(newItem);
JMenuItem quitItem = new JMenuItem("退出");
quitItem.setMnemonic(KeyEvent.VK_Q);
quitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.ALT_MASK));
quitItem.setActionCommand("quit");
quitItem.addActionListener(this);
fileMenu.add(quitItem);
bar.add(fileMenu);
return bar;
}
@Override
public void actionPerformed(ActionEvent e) {
if ("new".equals(e.getActionCommand())) createFrame();
else quit();
}
private void createFrame() {
MyInternalFrame frame = new MyInternalFrame();
frame.setVisible(true);
desktop.add(frame);
try { frame.setSelected(true); } catch (java.beans.PropertyVetoException ignored) {}
}
private void quit() { System.exit(0); }
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame f = new InternalFrameDemo();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
});
}
}
import javax.swing.*;
import java.awt.*;
public class MyInternalFrame extends JInternalFrame {
private static int count = 0;
private static final int OFFSET = 30;
public MyInternalFrame() {
super("文檔 #" + (++count), true, true, true, true); // 可縮放/關閉/最大化/最小化
getContentPane().add(new JTextArea(5, 20));
setSize(300, 300);
setLocation(OFFSET * count, OFFSET * count); // 錯開顯示,避免完全重疊
}
}
| 方法/屬性 | 說明 |
|---|---|
JInternalFrame(title, resizable, closable, maximizable, iconifiable) | 五參構造器全開啟窗體控制鈕 |
desktop.add(frame) | 將內部窗體加入桌面層級管理 |
frame.setSelected(true) | 激活並置頂(可能拋出 PropertyVetoException) |
desktop.setDragMode(OUTLINE_DRAG_MODE) | 拖動時僅繪製邊框輪廓,釋放後再重繪內容 |
frame.setIcon(true) | 程序化最小化為圖標(桌面底部) |
JInternalFrame,包含 JTextArea + 工具欄現代應用多採用單窗體 + 選項卡(JTabbedPane)或分割面板(JSplitPane)替代 MDI,降低認知負荷。若需保留 MDI,JavaFX 可通過 Stage + Scene 模擬,或使用第三方庫 DockFX、TornadoFX 實現可停靠窗格系統。