Xイベントシグナル

Widgetクラスの中には、バックエンドのX-Windowイベントと関連している特別なシグナルを持つものがあります。これらのシグナルには_eventの接尾辞が付いています。例えば、Widget::signal_button_pressed_event()です。

Xのイベントをハンドルすることはしばしば通常のシグナルでは結果が得られない場合に便利だと思うことでしょう。例えば、Gtk::Buttonはマウスポインタの座標をclickedシグナルに伝えることができません。この情報が必要な場合はbutton_pressed_eventをハンドルしてください。それ以外には、Xイベントはキー押下イベントをハンドルするのにもよく使われます。

これらのシグナルは通常のものとやや異なった振る舞いをします。シグナルハンドラが返す値が示すのは、そのイベントが完全に”ハンドルされている”かどうかです。値がfalseだった場合、gtkmmはイベントを次のシグナルハンドラに渡します。値がtrueだった場合はそれ以外のシグナルハンドラを呼び出す必要はありません。

Xのイベントをハンドルすることはそのウィジットの別のシグナルに影響を及ぼしません。Gtk::Buttonbutton_pressed_eventをハンドルしても、さらにclickedシグナルを捕捉することができます。これらのシグナルが発行されるのは(ほぼ)同時です。

以下のものはシンプルなコード例です:

bool on_button_press(GdkEventButton* event);
Gtk::Button button("label");
button.signal_button_press_event().connect( sigc::ptr_fun(&on_button_press) );

マウスがボタンの上を通過したときとマウスボタンが押されたときにon_button_pressed()が呼び出されます。

GdkEventButton型はイベントパラメータ(例えばボタンが押されたときのマウスポインタの座標など)を収めた構造体です。様々なイベントにたいして違った型のGdkEvent構造体があります。

シグナルハンドラのシーケンス

デフォルトでは自分で定義したシグナルハンドラが呼ばれるのは、それ以前に接続された全てのシグナルハンドラが呼ばれた後になります。ところが、これはXイベントシグナルでは問題がおこる場合があります。例えば、既存のシグナハンドラやデフォルトシグナルハンドラが戻り値にtrueを返して他のシグナルハンドラ呼び出しを止めてしまうことがあります。自分のシグナルハンドラが他のシグナルハンドラの前に呼ばれるように指定して、常に呼ばれるようにするには、connect()の追加のパラメータafterfalseを指定してください。このように:

button.signal_button_press_event().connect( sigc::ptr_fun(&on_mywindow_button_press), false );