コールバック関数


文字列を格納した領域を確保し、ボタンをクリックするたびにその文字列を標準出力へ表示し、 プログラムを閉じる際に領域を解放するサンプルを書いてみた。

#include <gtk/gtk.h>

static void cb_button(GtkWidget *widget, gpointer user_data)
{
  //ボタンのクリックで"Hello World"の文字列を受け取り、標準出力へ表示
  g_print( "%s\n", (gchar*)user_data );
}

static void destroy_data(gpointer user_data, GClosure *closure)
{
  //プログラムの終了でコールバック関数も終了
  g_print( "Destroy the callback function data.\n" );
  g_print( "The value of the destroyed data = '%s'\n", (gchar*)user_data );
  //"Hello World"の文字列用に確保していた領域を解放
  g_free( (gchar*)user_data );
}

int main(int argc, char** argv)
{
  GtkWidget *window;
  GtkWidget *button;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "Callback");
  gtk_widget_set_size_request(window, 250, 50);
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

  button = gtk_button_new_with_label("Click here");
  gtk_container_add(GTK_CONTAINER(window), button);
  //"Hello World"の文字列をボタンクリック用に格納(g_strdupで領域確保)
  g_signal_connect_data(G_OBJECT(button), "clicked", G_CALLBACK(cb_button), (gpointer*)g_strdup("Hello World"), destroy_data, 0);

  gtk_widget_show_all(window);
  gtk_main();

  return 0;
}

クリックするたびに、格納した"Hello World"の文字列を出力。

プログラムを閉じると、文字列を格納した領域を解放する。

ここでは、GObjectリファレンス・マニュアルを参照する。

g_signal_connect_dataの第4引数にg_strdupを用い、"Hello World"文字列を格納している。 第5引数には、コールバック関数が使用されなくなった時に呼び出される関数を指定する。


関数の呼び出し順


関数を呼び出す順番を設定できる。

#include <gtk/gtk.h>

static void cb_button1(GtkWidget *widget, gpointer user_data)
{
  g_print( "function 1.\n" );
}

static void cb_button2(GtkWidget *widget, gpointer user_data)
{
  g_print( "function 2.\n" );
}

static void cb_button3(GtkWidget *widget, gpointer user_data)
{
  g_print( "function 3.\n" );
}

static void cb_button4(GtkWidget *widget, gpointer user_data)
{
  g_print( "function 4.\n" );
}

int main(int argc, char** argv)
{
  GtkWidget *window;
  GtkWidget *button;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "Signal");
  gtk_widget_set_size_request(window, 250, 50);
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

  button = gtk_button_new_with_label("Click here");
  gtk_container_add(GTK_CONTAINER(window),button);
  //g_signal_connectの後に呼び出される関数
  g_signal_connect_after(G_OBJECT(button), "clicked", G_CALLBACK(cb_button3), NULL);
  g_signal_connect_after(G_OBJECT(button), "clicked", G_CALLBACK(cb_button4), NULL);
  //最初に呼び出される関数
  g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(cb_button1), NULL);
  g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(cb_button2), NULL);

  gtk_widget_show_all(window);
  gtk_main();

  return 0;
}

ボタンをクリックすると、cb_button1→cb_button2→cb_button3→cb_button4の順に処理される。

cb_button3とcb_button4を先に指定しているが、g_signal_connect_afterを用いているので、 後に指定したg_signal_connectのcb_button1とcb_button2の処理が終わった後に、処理が始まる。 これで、関数の処理のタイミングを設定できる。

ページが長くなるので、コールバック解除は次章で扱う事にする。


前章  | 目次 |  次章



トップ



/