GTK のシグナル関数とコールバック関数

GTK のシグナル関数とコールバック関数

  バージョン 2.0 では、信号システムが GTK から GLib に移行されたため、関数と型の宣言には「gtk_」ではなく「g_」が接頭辞として付けられます。
  GTK はイベント駆動型のツールキットです。つまり、次のイベントが発生するまで gtk_main() で待機してから、適切な関数に制御を渡します。制御の移行は「シグナル」メソッドを使用して行われます。(使用される用語は同じですが、ここでのシグナルは Unix シグナルと同等ではなく、Unix シグナルで実装されていないことに注意してください。)

1. よく使用される信号

  コンポーネントはさまざまな信号を送信できます。信号はユーザーの操作によって発生したり、関数シミュレーション イベントによって生成されたりすることができます。一般的な信号は次のとおりです。

メンバー 信号 意義 信号生成関数
ウィンドウズ "破壊" この信号は窓が閉まっているときに発せられます。
ボタン 「クリックされました」 ボタンをクリックします。これは、押す操作と離す操作を組み合わせたものです。 gtk_button_clicked(ボタン)
"入力" マウスオーバーボタン gtk_button_enter(ボタン)
"離れる" マウスの放置ボタン gtk_button_leave(ボタン)
「押された」 ボタンを押してください gtk_button_pressed(ボタン)
「解放された」 解除ボタン gtk_button_release(ボタン)
トグルボタン 「トグル」 スイッチボタン
リストボックス "選択する" リストボックスが選択されています
「選択_変更済み」 リストボックスの選択が変更される
GTKRadioMenuItem "活性化" メニューオプションが選択されました

  GTK+ の 2 つの基本メカニズムは、delete_event イベントdestroy シグナルです。ウィンドウが閉じようとすると、delete_event イベントが表示されます。ウィンドウが閉じられると、destroy 信号が発行されます。delete_event イベントの場合、トップレベル ウィンドウには対応するコールバック関数が必要です。delete_even は、ユーザーがアプリケーション ソフトウェアを閉じる必要があることを意味するためです。delete_event シグナルのコールバック関数を追加するには、2 つの手順が必要です。
  delete_event のコールバック関数は、ウィンドウを閉じることが許可されているかどうかを示すブール値を返す必要があります。TRUR の値を返すとウィンドウは開いたままになり、FALSEの値を返すとウィンドウを閉じてもよいことを示します。ウィンドウが閉じられている場合は、ウィンドウが閉じようとしていることをアプリケーションに伝えるために破棄信号が送信されます。

2. 信号接続と処理機能

2.1 シグナル接続関数 g_signal_connect

 /* 信号连接函数*/
#define g_signal_connect(instance, detailed_signal, c_handler, data)
形参:instance  --void*指针,要发出信号的构件
detailed_signal  -- char *指针,连接的信号的名称
      c_handler  --信号被捕获时所要调用的函数
      data   -- void*指针,传递给信号处理函数(回调函数)的数据
返回值:gulong类型,返回识别回调函数的标识
第三个参数即回调函数一般形式如下:
void callback_func( GtkWidget *widget,gpointer callback_data );
形参:widget -- 指向发出信号的构件的指针
      callback_data  --g_signal_connect传入的参数
注意:上面回调函数的声明只是一般的形式, 有些构件的特殊信号会用不同的调用参数。

  各信号と各オブジェクトには複数のコールバック関数を持つことができ、それらは設定された順序で順次実行されます。

2.2 g_signal_connect の戻り値

  シグナル接続関数 g_signal_connect の戻り値は glong 型で、コールバック関数を識別するフラグを返します。各信号と各オブジェクトには複数のコールバック関数を含めることができ、それらは設定された順序で順次実行されるためです。したがって、この戻りフラグを通じて、実装されたコールバック関数は次の関数を通じて削除できます。

g_signal_handler_disconnect(gpointer instance, gulong handler_id)

  したがって、ハンドラーを削除するコンポーネントと、signal_connect 関数によって返された識別子を渡すことによって、シグナル ハンドラーを切断できます。
  g_signal_handler_block() や g_signal_handler_unblock() などの関数を使用して、シグナル ハンドラーを一時的に切断することもできます。

void g_signal_handler_block (gpointer instance, gulong handler_id);
void g_signal_handlers_block_by_func( gpointer object,GCallback func,gpointer data );
void g_signal_handler_unblock (gpointer instance,gulong   handler_id);
void g_signal_handlers_unblock_by_func( gpointer object,GCallback func,gpointer data );

2.3 シグナル接続関数 g_signal_connect_swapped

/*信号连接函数*/
#define g_signal_connect_swapped(instance, detailed_signal, c_handler, data)
g_signal_connect_swapped()g_signal_connect() 相同,只是回调函数只用一个参数,一个指向GTK对象的指针。所以当使用这个函数连接信号时,回调函数应该是这样的形式:
	void callback_func( GtkObject *object );

  信号接続を設定するために 2 つの関数を用意する目的は、単にコールバック関数が異なる数の引数を持てるようにすることです。GTK ライブラリの多くの関数はパラメータとして 1 つのコンポーネント ポインタのみを受け入れるため、これらの関数には g_signal_connect_swapped() を使用しますが、自分で定義した関数の場合はコールバック関数に追加データを提供する必要がある場合があります。

3つのイベント

  シグナル メカニズムに加えて、X イベント メカニズムを反映する一連のイベントもあります。これらのイベントにはコールバック関数を付加できます。

• イベント
• button_press_event
• button_release_event
•scroll_event
•motion_notify_event
• delete_event
• destroy_event
• Expose_event
• key_press_event
• key_release_event •
enter_notify_event •
Leave_notify_event •
configure_event •
focus_in_event •
focus_out_event
•map_event •
unmap_event •
property_notify_event •
selection_clear_event •
selection_request_event •
selection_notify_event
•proximity_in_event
•proximity_out_event
•visibility_notify_event
•client_event
• no_expose_event
• ウィンドウ状態イベント

  コールバック関数をこれらのイベントのいずれかに接続するには、前述のように関数 g_signal_connect() を使用し、上記のイベント名の 1 つをdetailed_signal パラメーターとして指定します。イベント コールバック関数は、シグナル コールバック関数とは少し異なります。

gint callback_func( GtkWidget *widget,GdkEvent *event,gpointer callback_data );

  GdkEvent は C の共用体構造体で、そのタイプは上記のイベントのどれが発生したかによって異なります。どのイベントが発生したかを知るために、考えられる各型には、発生したイベントを反映する型メンバーがあります。イベント構造の残りの部分は、このイベントのタイプによって異なります。type に指定できる値は次のとおりです。

GDK_NOTHING
GDK_DELETE
GDK_DESTROY
GDK_EXPOSE
GDK_MOTION_NOTIFY
GDK_BUTTON_PRESS
GDK_2BUTTON_PRESS
GDK_3BUTTON_PRESS
GDK_BUTTON_RELEASE
GDK_KEY_PRESS
GDK_KEY_RELEASE
GDK_ENTER_NOTIFY
GDK_LEAVE_NOTIFY
GDK_FOCUS_CHANGE G DK_CONFIGURE
GDK_MAP
GDK_UNMAP
GDK_PROPERTY_NOTIFY
GDK_SELECTION_CLEAR
GDK_SELECTION_REQUEST
GDK_SELECTION_NOTIFY
GDK_PROXIMITY_IN
GDK_PROXIMITY_OUT
GDK_DRAG_ENTER
GDK_DRAG_LEAVE
GDK_DRAG_MOTION
GDK_DRAG_STATUS
GDK_DROP_START
GDK_DROP_FINISHED

GDK_CLIENT_EVENT
GDK_VISIBILITY_NOTIFY
GDK_NO_EXPOSE
GDK_SCROLL
GDK_WINDOW_STATE
GDK_SETTING

  したがって、コールバック関数をこれらのイベントのいずれかに接続するには、次のように使用します。

g_signal_connect (G_OBJECT (button), "button_press_event",G_CALLBACK (button_press_callback), NULL);

  ここではボタンをボタンウィジェットとする。ここで、マウスがボタンの上にあり、マウスが押されると、関数 button_press_callback() が呼び出されます。この関数は次のように宣言する必要があります。

static gint button_press_callback( GtkWidget *widget,
						GdkEventButton *event,
						gpointer data );

  どのタイプのイベントが発生するかはわかっているため、2 番目のパラメーターのタイプを GdkEventButton として宣言できることに注意してください。
  この関数の戻り値は、GTK イベント処理メカニズムによってイベントをさらに伝播する必要があるかどうかを示します。TRUE が返された場合は、このイベントが処理され、それ以上伝播すべきではないことを示します。通常のイベント処理を続行するには、FALSE を返します。

3.1 ボタン接続信号でウィンドウを閉じる例

#include <gtk/gtk.h>
void hello(GtkWidget *widget,gpointer data)
{
    
    
	g_print("按键信号触发成功\n");
}
/*事件处理回调函数*/
gint delete_event(GtkWidget *widget,GdkEvent *evnet,gpointer data)
{
    
    
	g_print("事件处理回调函数调用成功\n");
	return TRUE;//TRUE表示继续,FALSE表示关闭
}

void destroy(GtkWidget *widget,gpointer data)
{
    
    
	g_print("销毁窗口\n");
	gtk_main_quit();//退出程序
}
int main(int argc,char *argv[])
{
    
    
	GtkWidget *window;
	GtkWidget *button;
	/*gtk初始化*/
	gtk_init(&argc, &argv);
	/*创建窗口*/
	window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW(window),"GTK");/*设置窗口标题*/
	/*信号连接函数*/
	g_signal_connect(GTK_OBJECT(window),"delete_event",G_CALLBACK(delete_event),NULL);
	g_signal_connect(GTK_OBJECT(window),"destroy", G_CALLBACK(destroy), NULL);
	/*设置容器对象属性:设置窗口边框宽度为100*/
	gtk_container_set_border_width(GTK_CONTAINER(window),100);
	/*创建新的按钮,设置按钮信息为hello*/
	button=gtk_button_new_with_label("hello");
	g_signal_connect(GTK_OBJECT(button),"clicked",G_CALLBACK(hello),NULL);
	g_signal_connect_swapped(GTK_OBJECT(button),"clicked",G_CALLBACK(gtk_widget_destroy),GTK_OBJECT(window));
	/*将按钮放入窗口中*/
	gtk_container_add(GTK_CONTAINER(window),button);
	/*显示控件*/
	gtk_widget_show_all(window);
	/*等待事件*/
	gtk_main();
	return 0;
}

ここに画像の説明を挿入

  • プログラム実行効果:

  マウスで hello ボタンを押すと、ボタンはクリック信号を送信し、hello コールバック関数をトリガーして、次の信号処理関数 gtk_widget_destroy() を呼び出し、ウィンドウ コンポーネントのパラメーターをこの関数に渡し、ウィンドウを破棄し、 window は destroy シグナルを送信し、プログラムの終了を実現する番号のコールバック関数 destroy() を呼び出します。

おすすめ

転載: blog.csdn.net/weixin_44453694/article/details/127372355