MDI (Multiple Document Interface)型のアプリをJavaでも作ることができます。
MDI型、SDI型アプリとは
MDI型のアプリとは、今回のサンプルで作っているこんな画面のアプリのことです。

親画面の中に子画面が入っていて、親画面の範囲内で子画面を動かしたり、最大化したり、最小化したりできます。
これに対するのはSDI (Single Document Interface)型アプリ。
こちらのサイトで紹介している「ブログ記事作成支援アプリ」は、以前はSDI型でした。

普通にJFrameで作っていたらこのような形になります。
それぞれの画面が独立して動いているような感じです。
もちろん、MDIとSDIのどちらが優れているということはないです。
作るアプリ次第でどちらがいいかを選んだらよいです。
MDI型アプリを作ってみよう!
それではサンプルコードを見て行きましょう。
前半は起動のためのコードなので読み飛ばしてください。
大切なのは42行目からのinitialize()メソッドです。
package jp.beourselves.open.sample.jdesktop;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
public class JDesktopPaneSample1 {
	private JFrame frmMdi;
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					JDesktopPaneSample1 window = new JDesktopPaneSample1();
					window.frmMdi.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
	/**
	 * Create the application.
	 */
	public JDesktopPaneSample1() {
		initialize();
	}
	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmMdi = new JFrame();
		frmMdi.setTitle("MDI型アプリ サンプル");
		frmMdi.setBounds(100, 100, 450, 400);
		frmMdi.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		JDesktopPane desktopPane = new JDesktopPane();
		frmMdi.getContentPane().add(desktopPane, BorderLayout.CENTER);
		
		JInternalFrame frame1 = new JInternalFrame("Frame1");
		frame1.setBounds(0, 0, 200, 300);
		desktopPane.add(frame1);
		
		JLabel lblHelloJdesktoppane = new JLabel("Hello, JDesktopPane!");
		lblHelloJdesktoppane.setHorizontalAlignment(SwingConstants.CENTER);
		frame1.getContentPane().add(lblHelloJdesktoppane, BorderLayout.CENTER);
		
		JInternalFrame frame2 = new JInternalFrame("Frame2");
		frame2.setBounds(200, 0, 200, 200);
		desktopPane.add(frame2);
		
		JLabel lblHelloJinternalframe = new JLabel("Hello, JInternalFrame");
		lblHelloJinternalframe.setHorizontalAlignment(SwingConstants.CENTER);
		frame2.getContentPane().add(lblHelloJinternalframe, BorderLayout.CENTER);
		frame2.setVisible(true);
		frame1.setVisible(true);
	}
}
このコードを実行するとこんな画面が出てきます。

タイトルバーに「MDI型アプリ サンプル」という親画面があり、その中に「Frame1」、「Frame2」という子画面が入っている、という感じです。
試しに「Frame1」や「Frame2」を移動させてみても、「MDI型アプリ サンプル」という親画面の外には出ることができません。
「MDI型アプリ サンプル」画面の中で完結しています。
JDesktopPaneとJInternalFrameを使って親子画面を作る
肝になるのはJDesktopPaneとJInternalFrameを使うことです。
イメージ的には、
- JDesktopPaneで親画面を作り (48〜49行目)
- JInternalFrameで子画面を作り(51〜52行目)
- 子画面を親画面に貼り付ける (53行目)
ような感じです。
JDesktopPaneで親画面を作る
まずは親画面を作るJDesktopPaneを見て行きましょう。
43〜49行目になります。
		frmMdi = new JFrame();
		frmMdi.setTitle("MDI型アプリ サンプル");
		frmMdi.setBounds(100, 100, 450, 400);
		frmMdi.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		JDesktopPane desktopPane = new JDesktopPane();
		frmMdi.getContentPane().add(desktopPane, BorderLayout.CENTER);
最初の4行は親画面となるJFrameを作っています。
タイトルを設定し、サイズを設定し、閉じるときの処理を書いています。
最後の2行でJDesktopPaneを先に作ったJFrameに貼り付けています。
これで親画面の準備ができました。
JInternalFrameで子画面を作る
続いて子画面です。
「Frame1」を作っている51〜57行目を見てください。
		JInternalFrame frame1 = new JInternalFrame("Frame1");
		frame1.setBounds(0, 0, 200, 300);
		desktopPane.add(frame1);
		
		JLabel lblHelloJdesktoppane = new JLabel("Hello, JDesktopPane!");
		lblHelloJdesktoppane.setHorizontalAlignment(SwingConstants.CENTER);
		frame1.getContentPane().add(lblHelloJdesktoppane, BorderLayout.CENTER);
最初の3行で子画面を作って、親画面に貼り付けています。
setBounds()で親画面内の表示位置とサイズを設定しています。
setBounds(x, y, dx, dy)
- x: 表示位置のx座標 (親ウインドウ内の座標)
- y: 表示位置のy座標 (親ウインドウ内の座標)
- dx: 子画面の横幅
- dy: 子画面の縦幅
最後の3行は作った子画面にラベルを貼り付けています。
59〜65行目は同じ処理なので省略しますね。
子画面を表示する
そして、66〜67行目で、貼り付けた子画面を表示しています。
frame2.setVisible(true); frame1.setVisible(true);
この処理を忘れると子画面がいないアプリになります。
必ずsetVisible(true)を設定しましょう。
JFrameの画面をJInternalFrameの画面に変換する
もうすでにJFrameで画面を作ったものがあったら、JFrameを継承する代わりにJInternalFrameを継承するようにしてください。
ほとんどそのまま子画面にすることができると思います。
改めて最初から子画面を作るよりは、こうして改造した方が早いでしょう。
ブログ記事作成支援ツールをMDI型にした時は、ほとんどそのまま変換できました。
おわりに
以上のように、JDesktopPaneとJInternalFrameを使うことでJavaでもMDI型のアプリが作れます。
ただ、これだけだと子画面の最大化、最小化、閉じるといった画面操作はできません。
その辺りはまた改めて作り方を紹介します。

元大手電機メーカのシステムエンジニア。
詳しくはこのサイトについての「サイト管理者について」をご覧ください。

