![]() |
![]() |
![]() |
コールバック関数の共有
今までは、1つのボタンに1つの役割を持たせて来た。 今回は、2つのボタンに同じ処理をさせてみる。
|
#include <gtk/gtk.h> static void cb_button(GtkWidget *widget, gpointer user_data) { static gint count = 0; gchar buf[64]; if( count < 1 ){ sprintf( buf, "%d time clicked.", ++count); } else { sprintf( buf, "%d times clicked.", ++count); } gtk_button_set_label(GTK_BUTTON(widget), buf); } int main(int argc, char** argv) { GtkWidget *window; GtkWidget *hbox; GtkWidget *button1; GtkWidget *button2; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Count"); gtk_widget_set_size_request(window, 500, 50); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_container_add(GTK_CONTAINER(window), hbox); button1 = gtk_button_new_with_label("0 time clicked."); gtk_box_pack_start(GTK_BOX(hbox), button1, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK(cb_button), NULL); button2 = gtk_button_new_with_label("Click here"); gtk_box_pack_start(GTK_BOX(hbox), button2, TRUE, TRUE, 0); //button1クリック時と同じ関数を呼び出す
g_signal_connect_swapped(G_OBJECT(button2), "clicked", G_CALLBACK(cb_button), (gpointer)button1);gtk_widget_show_all(window); gtk_main(); return 0; } |
右のボタンをクリックすると、左のボタン・ラベルがカウント表示される。
左のボタンをクリックしても、同様に左のボタン・ラベルがカウント表示される。
g_signal_connect_swappedの第1引数(button2)には、 第4引数(button1)で指定したウィジェットが渡される。
これを用いれば、複数ボタンのクリックで、同一関数の処理を行う事ができる。
コールバック関数の解除
ボタンのクリックにより関数処理を行なって来たが、 プログラム実行中にその役目を終えさせる事もできる
|
#include <gtk/gtk.h> static void cb_button(GtkWidget *widget, gpointer user_data) { //コールバック関数に設定されていれば実行される
g_print( "Callback function is called.\n" );} static void disconnect_handler(GtkWidget *widget, gpointer user_data) { GtkWidget *button; gulong handle; button = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "button1")); handle = (gulong)g_object_get_data(G_OBJECT(widget), "handle"); //コールバック関数が解除されていない場合
if(g_signal_handler_is_connected(button, handle)){ //buttonウィジェットをコールバック関数の指定ID(handle)から解除
g_signal_handler_disconnect(button, handle);g_print( "Callback function is disconnecter.\n" ); return; } //コールバック関数が解除されている場合
else{ //すでに解除されている事を表示
g_print( "Callback function is already disconnecter.\n" );} } int main(int argc, char** argv) { GtkWidget *window; GtkWidget *hbox; GtkWidget *button1; GtkWidget *button2; gulong handle; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Disconnect"); gtk_widget_set_size_request(window, 500, 50); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_container_add(GTK_CONTAINER(window), hbox); button1 = gtk_button_new_with_label("button1"); gtk_box_pack_start(GTK_BOX(hbox), button1, TRUE, TRUE, 0); //コールバック関数のIDを指定
handle = g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK(cb_button), NULL);button2 = gtk_button_new_with_label("Disconnect button1 callbacks."); //GObject型の変数を関連付ける(g_object_set_data)
g_object_set_data(G_OBJECT(button2), "button1", (gpointer)button1);g_object_set_data(G_OBJECT(button2), "handle", (gpointer)handle); gtk_box_pack_start(GTK_BOX(hbox), button2, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(disconnect_handler), NULL); gtk_widget_show_all(window); gtk_main(); return 0; } |
「button1」ボタンをクリックすると、登録されているコールバック関数が処理される。
「Disconnect button1 callbacks.」ボタンをクリックする事で、 button1のコールバック関数を解除する。 再び「button1」ボタンをクリックしても、処理されなくなる。
サンプルではbutton1の登録を解除させた事で、解除ボタンの役目を終えたメッセージを表示させている。
サンプルでは、g_object_set_dataを用いている。
第1引数:オブジェクト、第2引数:関連付ける変数識別の文字列、第3引数:関連付ける変数、である。
また、関連付けた変数を取得するg_object_get_dataも有る。
第1引数:オブジェクト、第2引数:関連付ける変数識別の文字列、となる
コールバック関数の解除にはg_signal_handler_disconnectを用いた。
解除されているかを確認するのに、g_signal_handler_is_connectedが使える。
第1引数:コールバック関数を登録したオブジェクト、第2引数:コールバック関数IDである。
プログラム終了前の確認
プログラムを閉じる時に、本当に終了してよいか、確認するダイアログを表示させる。
|
#include <gtk/gtk.h> static gboolean cb_delete(GtkWidget *widget, gpointer user_data) { GtkWidget *dialog; gint result; //YESかNOを選択するダイアログを表示
dialog = gtk_message_dialog_new(GTK_WINDOW(widget), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "Confirm are you sure you want to quit.");result = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); //YESを選択した場合
if(result == GTK_RESPONSE_YES){ //destroyシグナルが発生(指定したcb_destroy関数へ)
return FALSE;} //NOを選択した場合
else{ //何も発生しない
return TRUE;} } static void cb_destroy(GtkWidget *widget, gpointer user_data) { //プログラムを終了
gtk_main_quit();} int main(int argc, char** argv) { GtkWidget *window; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Delete"); gtk_widget_set_size_request(window, 250, 50); //ウィンドウを閉じる際に、delete-eventシグナルを発生させる
g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(cb_delete), NULL);g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(cb_destroy), NULL); gtk_widget_show_all(window); gtk_main(); return 0; } |
ウィンドウを閉じる前に確認。
「はい(Y)」をクリックしてプログラムを終了。