ウィンドウサイズをiniファイルに保存、復元するサンプル

swingでアプリケーション再起動時にウィンドウのサイズと位置、最大化/最小化などを復元したかったので調べてみました。

ポイント

  • ウィンドウの位置、サイズが変わるたび、変数にウィンドウの位置とサイズを記録しています。
  • アプリケーションの終了時に変数の内容をiniファイルに保存しています。
  • アプリケーション起動時にiniファイルを読み込み、復元しています。
    • ウィンドウのステータス(最小化/最大化/通常)も記録しているため、最小化/最大化/通常も復元しています。
  • 最大化時、最小化時にウィンドウを元に戻した大きさを知る方法はないようです。
    • ※これさえあればもっと簡単なのですが、2chで聞いた限りでは残念ながらないようです。
  • 最大化/通常化をしていると最大化後のウィンドウの位置を記録する事があります。
    • 仕方ないので、最大化の通知時に最後の座標記録時間との差が短ければ位置の保存をキャンセルするようにしました。
    • ※この方法でも、プラットフォームによっては最大化途中のサイズを記録してしまうそうです。
    • 気が向いたら、もう少し修正してみます。気が向いたら。

実行結果1

save.ini

x=100
y=100
w=388
h=135
e=0

実行結果2

save.ini

x=201
y=183
w=183
h=217
e=0

ソース saveWindowSize.java

import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
 
import javax.swing.JFrame;
 
/**
 * ウィンドウサイズをiniファイルに保存、復元するサンプル
 */
public class saveWindowSize extends JFrame {
	// iniファイルの名前
	private static final String SAVE_INI = "save.ini";
	// 座標記録用
	Point pt = new Point();
	// 最大化の時の巻き戻し用
	Point ptbk = new Point();
	// 座標を記録した時間
	Date ptDate = new Date();
	// 幅と高さ
	Dimension dim = new Dimension();
	// 読み込んだiniファイルの内容を保持するマップ
	Map<String, String> iniMap;
 
	public static void main(String[] args) {
		new saveWindowSize();
	}
 
	// コンストラクタ
	saveWindowSize() {
		init();
	}
 
	// 初期化メソッド
	public void init() {
		// iniファイルを読み込み
		iniMap = loadIni();
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		int x = getIniInt("x", 100);
		int y = getIniInt("y", 100);
		int w = getIniInt("w", 300);
		int h = getIniInt("h", 200);
		int e = getIniInt("e", 0);
		this.setTitle("ウィンドウサイズをiniファイルに保存、復元サンプル");
 
		// ウィンドウ閉じる時にiniファイルを記録する
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				saveIni();
			}
		});
		addComponentListener(new ComponentAdapter() {
			// ウィンドウが動いたら位置を記録する
			@Override
			public void componentMoved(ComponentEvent e) {
				// ウィンドウが通常の時だけウィンドウの位置を記録
				// 最大化後のサイズを記録する事があるので、一つ履歴を保持する
				if (getExtendedState() == JFrame.NORMAL && isShowing()) {
					// 最大化サイズを記録した場合に戻す様の履歴
					ptbk.setLocation(pt);
					// 現在のサイズを記録
					pt.setLocation(getLocationOnScreen());
					// 時間も記録
					ptDate = new Date();
					// 座標を出力
					System.out.println("" + pt.x + "," + pt.y);
				}
			}
 
			// ウィンドウサイズが変化したらサイズを記録
			@Override
			public void componentResized(ComponentEvent e) {
				// ウィンドウが通常の時だけサイズを記録
				if (getExtendedState() == JFrame.NORMAL) {
					dim.setSize(getSize());
				}
			}
		});
 
		// ウィンドウが最大化/最小化/通常になると呼び出される
		addWindowStateListener(new WindowStateListener() {
			@Override
			public void windowStateChanged(WindowEvent e) {
				// 最大化された場合
				if (getExtendedState() == JFrame.MAXIMIZED_BOTH) {
					// ウィンドウの位置を記録してから1秒以内に最大化通知が来たら、履歴から座標を戻す
					long l = new Date().getTime();
					if (l - ptDate.getTime() < 1000) {
						System.out.println("最大化座標を記録したかもなのでもとに戻す");
						pt.setLocation(ptbk);
					}
				}
			}
		});
 
		// ウィンドウのサイズと座標を設定
		this.setBounds(x, y, w, h);
		// ウィンドウの状態を設定(通常/最小化/最大化など)
		this.setExtendedState(e);
		// 記録用変数にサイズを保存
		dim.setSize(w, h);
		// 記録用変数に座標を保存
		pt.setLocation(x, y);
		ptbk.setLocation(x, y);
		// 時間も保存しとく
		ptDate = new Date();
 
		setVisible(true);
	}
 
	// iniファイルを読み込み、Mapに詰めて返します。
	public Map<String, String> loadIni() {
		File f = new File(SAVE_INI);
		Map<String, String> map = new HashMap<String, String>();
		try {
			FileReader fr = new FileReader(f);
			BufferedReader br = new BufferedReader(fr);
			String line;
			while ((line = br.readLine()) != null) {
				int i = line.indexOf('=');
				if (i < 0)
					continue;
				String key = line.substring(0, i);
				String value = line.substring(i + 1);
 
				map.put(key, value);
			}
 
			br.close();
			fr.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return map;
	}
 
	// iniファイルを保存します
	public void saveIni() {
		File f = new File(SAVE_INI);
		try {
			FileWriter fw = new FileWriter(f);
			BufferedWriter bw = new BufferedWriter(fw);
			bw.write("x=" + pt.x);
			bw.newLine();
			bw.write("y=" + pt.y);
			bw.newLine();
			bw.write("w=" + dim.width);
			bw.newLine();
			bw.write("h=" + dim.height);
			bw.newLine();
			bw.write("e=" + getExtendedState());
			bw.newLine();
			bw.close();
			fw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
 
	// iniファイルから値を取得します。
	// 取得できない場合はデフォルト値を返します
	public int getIniInt(String key, int defaultValue) {
		if (iniMap.containsKey(key)) {
			try {
				return Integer.parseInt(iniMap.get(key));
			} catch (NumberFormatException e) {
				// 握りつぶす
			}
		}
		return defaultValue;
	}
}
 
最終更新:2012年09月23日 01:43