OSTRACISM CO.

C#とObjective-CとJavaと...

終了

 GUIツールを開発するときにまず最初に用意するのは終了方法だ。起動して終了するだけ。

C#

[STAThread]
static void Main() {
	Application.Run(new GGG4W());
}
 プログラムの最上位は、ApplicationクラスのRunメソッドに自プログラムの最上位クラスの新規インスタンスを渡すことで動き出す。このインスタンスが終了するとプログラム全体も終了する。
 自プログラムの最上位クラスはSystem.Windows.Forms.Formを継承しており、ウィンドウが閉じられるとインスタンスも消去され、プログラムも終了する。
private void menuExit_Click(object sender, System.EventArgs e) {
	Close();
}
 メニューで終了を選択された場合もウィンドウを閉じることでプログラムを終了する。
private void GGG4W_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
	...
	m_gs.Join();
}

public void Join() {
	Stop();
	while (IsWorking()) {
		Thread.Sleep(0);
	}
}
 ウィンドウが閉じられるとClosingイベントが発生するので、必要な後始末を記述する。
 上記Joinは検索中にウィンドウを閉じられたときにスレッドの合流(join)をするコードで、正常に中断させる。

Objective-C

int main(int argc, char *argv[])
{
    return NSApplicationMain(argc,  (const char **) argv);
}
 プログラムの最上位は、NSApplicationMain関数の呼び出しで、.nibの読み込み等必要な初期化を行った後メインウィンドウを表示する。
 メインウィンドウが閉じられても自動的にはプログラムは終了しない。
 Mac OSは伝統的にウィンドウのないメニューだけの状態が許されており、プログラム終了とウィンドウの状態に関連はない。

 メニューで終了を選択された場合プログラムは終了するが、「終了する」というterminateイベントは自メインクラス(GGG4Mクラス)ではなくNSApplicationクラスに渡る。
- (void)windowWillClose:(NSNotification *)notif {
	...
		[m_gs join];
	...
	[[NSApplication sharedApplication] terminate:self];
}

- (void)join {
	[self stop];
	while ([self isWorking]) {
		sleep(0);
	}
}
 メニューで終了してもクローズボックスをクリックしてもwindowWillCloseのイベントは発生するので、そこで後始末をする。また、クローズボックスのクリックでは終了するコードはないので、NSApplicationクラスに対してterminateを呼び出す。なぜかwindowWillCloseが2度呼ばれてしまうが、どう終わらせるのが正しいのかはいまだ研究中である。
 上記joinは検索中にウィンドウを閉じられたときにスレッドの合流(join)をするコードで、正常に中断させる。

Java

public static void main(String args[]) {
	java.awt.EventQueue.invokeLater(new Runnable() {
		public void run() {
			m_mainWindow = new GGG4J();
			m_mainWindow.setVisible(true);
		}
	});
}
 プログラムの最上位は、java.awt.EventQueueに対して無名のRunnableクラスを定義、新規インスタンスを遅延呼び出ししている。
 単純にGGG4Jクラスのインスタンスを得て、setVisible(true)するだけでいいのだが、NetBeansはこういう記述にする。何か意味があるんだろうとは思うがその意味は想像するしかない。
 GGG4JクラスのウィンドウはダイアログではないのでsetVisible(true)は他のスレッドをブロックしない。
private void menuExitActionPerformed(java.awt.event.ActionEvent evt) {
	onClosing(null);
}

private void onClosing(java.awt.event.WindowEvent evt) {                           
	...
	m_gs.join();
	System.exit(0);
}                          

public void join() {
	if (isWorking() == false)
		return;
	stop();
	try {
		m_work.join();
	}
	catch (Exception e) {
	}
}
 ウィンドウが閉じられるとwindowClosingイベントが発生するのでwindowClosingから呼び出しているonClosingで必要な後始末を記述する。
 setVisible(false)をすることでプログラムが終了しても良さそうだが、どうもそのあたりの動きはまだ追いきれていない。よってメインウィンドウが閉じられたら明示的にSystem.exitを呼び出してプログラムを終了させる。
 上記joinは検索中にウィンドウを閉じられたときにスレッドの合流(join)をするコードで、正常に中断させる。

 以上で「C#とObjective-CとJavaと...」で終わるが、GraphicGripGropが完成しているわけではないことはお気づきかと思う。GUIプログラムとして必須なメニューの有効無効の制御やダイアログ中のカットアンドペーストなどが実装されていない。概ねGUIプログラムがどんな風に組まれるのかといった説明に邪魔になる瑣末な機能は省いているからだ。
 気が向いたら用意できる環境のGraphicGripGropの改造をしてみてほしい。

2005.08.02
2005.09.18
「インデックス」へ戻る

OSTRACISM CO.
OSTRA / Takeshi Yoneki