2.4.4 シグナルとコールバック関数の使用例

 最後に、GTK+におけるシグナルとコールバック関数(シグナルハンドラ)のよくある使用例について説明して、この節を終わります。

 たいていのGTK+アプリケーションは、トップレベルウィンドウ(=デスクトップ画面に単独で存在できるウィンドウ。例えば、GtkWindowウィジェット)のdelete-eventシグナルに、gtk_main_quit関数を呼び出す処理を含むシグナルハンドラをconnectしています。delete-eventシグナルは、プログラムのユーザがウィンドウを閉じようとした時、例えばクローズボタンを押した時などに発生するシグナルです。

プログラマが上記のようなdelete-eventシグナルのハンドラをconnectするのには理由があり、原因はdelete-eventシグナルのデフォルトのハンドラの仕様にあります。デフォルトハンドラとは、プログラマが明示的にconnectするハンドラとは別に、文字通りデフォルトでconnectされているハンドラのことです。

このdelete-eventシグナルのデフォルトハンドラ内では、トップレベルウィンドウが破棄される(=画面上・メモリ上から消滅して、プログラムのユーザはもちろんプログラマからも利用できなくなる)のですが、ハンドラを抜けた後もプログラムのメインループは回り続けます。このハンドラは、あくまで関連付けられたウィンドウを破棄する責任のみを負っているからです。

このことは、トップレベルウィンドウを1つしか使わないプログラムの場合、プログラムが動き続けるにもかかわらず、プログラムのユーザが、(通常の方法では)プログラムを終了する手段がなくなってしまうことを意味します。そして、この動作にどう対処するかは、プログラマが決める必要があります。具体的には、自分で適切な処理を記述したハンドラをdelete-eventシグナルにconnectします。

 ここで言う適切な処理には、おもに2種類あり、1つは、メインループを抜けてプログラムを終了させるもので、もう1つは、デフォルトハンドラの実行をキャンセルして、ユーザのウィンドウを閉じる操作をなかったことにするものです。プログラマがdelete-eventシグナルにconnectしたハンドラは、デフォルトハンドラよりも先に実行されるため、このような処理が可能になっています。

 メインループを抜けてプログラムを終了させる場合には、この項の冒頭に挙げたgtk_main_quit関数を呼び出します。この場合、すべてのシグナルハンドラからreturn後、プログラムの実行位置が、メインループに入るためのgtk_main関数の呼び出しの直後に戻りますので、その場所にend命令を書いておいて、実際にプログラムを終了させてください。

 デフォルトハンドラの実行をキャンセルしたい場合には、0以外の数値(C言語で真と評価される値)をreturnします。この場合、ウィンドウは破棄されずにそのまま表示され続け、引き続き操作が可能です。

 これら2つの処理のどちらを実行するかは、状況によってif文などで選択します。例えば、ユーザにウィンドウを閉じて良いか確認するダイアログを表示して、その結果を条件として判断するなどします。あるいは、もし状況判断が必要なく、常に終了させたいのであれば、gtk_main_quitの呼び出しだけを書いておけばOKです。

 以上で説明した、gtk_main_quit関数を呼び出すシグナルハンドラは、どんなGTK+アプリケーションでも必要なので、覚えておくようにしてください。

Prev - Table of contents - Next