C言語のGTK+でListStoreからデータを取り出す処理に関する追加メモ(後半)
「C言語のGTK+でListStoreからデータを取り出す処理に関する追加メモ(前半)」の続き。
「C言語でGTK+ 2を扱う上での幾つかのメモ(第9回)」の例と同じ処理をgtk_tree_model_get()を用いたものに書き換えると下のようになり、動作は同じものとなる。
[任意]ファイル名: treeviewliststoretest2.c
#include <gtk/gtk.h> #include <stdlib.h> /* * C言語によるGTK+のTreeView(ListStore使用)のテスト2 * gtk_tree_model_get()を用いた例 * * gcc -O2 -Wall -Wextra $(pkg-config --cflags --libs gtk+-2.0) treeviewliststoretest2.c -o treeviewliststoretest2 */ enum { COLUMN_A, /* 最初は0 */ COLUMN_B, COLUMN_C, NUM_COLUMNS, /* 最後のコラム番号の次がコラム数になる */ }; void on_button_clicked (GtkTreeView *tv) /* swapped指定なのでボタンではない */ { gboolean ret_a; gint ret_b; gchar *ret_c; GtkTreeIter iter; GtkTreeSelection *selection; GtkTreeModel *model; selection = gtk_tree_view_get_selection (tv); /* * 現在ツリービュー上で選択されている項目(全コラムのまとまり)を取得 * ツリービューに関連付けられているモデル(ここではListStore)の場所を受け取って * 内容にアクセスできるようにする(コピーするのではない) * 関数の中でmodelとiterの内容が書き換えられる */ gtk_tree_selection_get_selected (selection, &model, &iter); /* 各コラムの値をListStoreからそれぞれ取り出して書き込む */ gtk_tree_model_get (model, &iter, COLUMN_A, &ret_a, COLUMN_B, &ret_b, COLUMN_C, &ret_c, -1); /* それぞれを端末に表示 */ g_print ("A:%s B:%d C:%s\n", ((ret_a) ? "TRUE" : "FALSE"), ret_b, ret_c); /* 文字列はg_free()で解放する */ g_free (ret_c); } int main (int argc, char **argv) { GtkListStore *ls; GtkWidget *mainwindow, *menubar, *tv, *sw, *button, *vbox; GtkWidget *item_quit, *item_file, *menu_file; GtkAccelGroup *accelgroup; GtkTreeIter iter; GtkTreeViewColumn *col_a, *col_b, *col_c; gtk_init (&argc, &argv); mainwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); /***** ショートカットキー(アクセラレータ) *****/ accelgroup = gtk_accel_group_new (); gtk_window_add_accel_group (GTK_WINDOW (mainwindow), accelgroup); /***** メニュー項目 *****/ item_quit = gtk_image_menu_item_new_from_stock (GTK_STOCK_QUIT, accelgroup); menu_file = gtk_menu_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu_file), item_quit); item_file = gtk_menu_item_new_with_mnemonic ("_File"); gtk_menu_item_set_submenu (GTK_MENU_ITEM (item_file), menu_file); menubar = gtk_menu_bar_new (); gtk_menu_bar_append (GTK_MENU_BAR (menubar), item_file); /***** ツリービュー *****/ /*** コラム ***/ /* 最初の2つの引数は表示文字列とセルレンダラオブジェクト */ col_a = gtk_tree_view_column_new_with_attributes ("Column A", gtk_cell_renderer_toggle_new (), /* 「[セルレンダラのGObjectプロパティ名], [コラム番号]」の繰り返し */ "active", COLUMN_A, NULL); /* 最後にNULL */ col_b = gtk_tree_view_column_new_with_attributes ("Column B", gtk_cell_renderer_text_new (), "text", COLUMN_B, NULL); col_c = gtk_tree_view_column_new_with_attributes ("Column C", gtk_cell_renderer_text_new (), "text", COLUMN_C, NULL); /*** データ(ListStore) ***/ ls = gtk_list_store_new (NUM_COLUMNS, G_TYPE_BOOLEAN, /* 真偽値 */ G_TYPE_INT, /* 整数 */ G_TYPE_STRING); /* 文字列 */ /*** ツリービューとその設定 ***/ tv = gtk_tree_view_new_with_model (GTK_TREE_MODEL (ls)); /* モデルと関連付け */ gtk_tree_view_append_column (GTK_TREE_VIEW (tv), col_a); gtk_tree_view_append_column (GTK_TREE_VIEW (tv), col_b); gtk_tree_view_append_column (GTK_TREE_VIEW (tv), col_c); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tv), TRUE); sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add (GTK_CONTAINER (sw), tv); /* * ListStoreへのデータの追加 * 今回 * (FALSE, 12345, "test"), (TRUE, 99999, "GTK+"), (FALSE, 838861, "ListStore") * という3つのデータを続けて追加するものとする */ gtk_list_store_append (ls, &iter); gtk_list_store_set (ls, &iter, COLUMN_A, FALSE, /* コラム番号と値のペア(引数2つ単位) */ COLUMN_B, 12345, COLUMN_C, "test", -1); /* -1を最後に付ける */ gtk_list_store_append (ls, &iter); gtk_list_store_set (ls, &iter, COLUMN_A, TRUE, COLUMN_B, 99999, COLUMN_C, "GTK+", -1); gtk_list_store_append (ls, &iter); gtk_list_store_set (ls, &iter, COLUMN_A, FALSE, COLUMN_B, 838861, COLUMN_C, "ListStore", -1); /***** ボタン *****/ button = gtk_button_new_with_mnemonic ("_Get"); /***** 垂直ボックス(縦方向分割) *****/ vbox = gtk_vbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); /***** ウィンドウ *****/ gtk_container_add (GTK_CONTAINER (mainwindow), vbox); gtk_widget_show_all (mainwindow); gtk_widget_set_size_request (mainwindow, 250, 160); gtk_window_resize (GTK_WINDOW (mainwindow), 300, 220); /***** シグナル *****/ g_signal_connect (G_OBJECT (mainwindow), "delete-event", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect (G_OBJECT (item_quit), "activate", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect_object (G_OBJECT (button), "clicked", G_CALLBACK (on_button_clicked), G_OBJECT (tv), G_CONNECT_SWAPPED); /***** メインループ開始 *****/ gtk_main (); return EXIT_SUCCESS; }
オブジェクト(GdkPixbuf)をListStoreに入れた例は下のようになる。
[任意]ファイル名: treeviewliststoretest3.c
#include <gtk/gtk.h> #include <stdlib.h> /* * C言語によるGTK+のTreeView(ListStore使用)のテスト3 * gtk_tree_model_get()を用いた例・データにオブジェクト(GdkPixbuf)を使用 * * gcc -O2 -Wall -Wextra $(pkg-config --cflags --libs gtk+-2.0) treeviewliststoretest3.c -o treeviewliststoretest3 */ static const char *xpm1[] = { "16 16 2 1", " c None", ". c #FF6666", " ...... ", " ........ ", " ............ ", " ............ ", " .............. ", "................", "................", "................", "................", "................", "................", " .............. ", " ............ ", " ............ ", " ........ ", " ...... "}; static const char *xpm2[] = { "16 16 2 1", " c None", ". c #EDDB20", " ", " .. ", " .. ", " .... ", " .... ", " .......... ", "................", " .............. ", " ............ ", " .......... ", " ........ ", " ........ ", " .......... ", " .......... ", " ... ... ", " . . "}; static const char *xpm3[] = { "16 16 2 1", " c None", ". c #2995E0", " .......... ", " .............. ", "................", "................", "................", " .............. ", " .............. ", " .............. ", " ............ ", " ............ ", " .......... ", " ........ ", " ........ ", " ...... ", " .... ", " .. "}; enum { COLUMN_A, /* 最初は0 */ COLUMN_B, NUM_COLUMNS, /* 最後のコラム番号の次がコラム数になる */ }; void on_button_clicked (GtkTreeView *tv) /* swapped指定なのでボタンではない */ { gint ret_a; GObject *ret_b; gint i, j; int width, height; int n_channels; GtkTreeIter iter; GtkTreeSelection *selection; GtkTreeModel *model; guchar *p, *r, *g, *b; selection = gtk_tree_view_get_selection (tv); /* * 現在ツリービュー上で選択されている項目(全コラムのまとまり)を取得 * ツリービューに関連付けられているモデル(ここではListStore)の場所を受け取って * 内容にアクセスできるようにする(コピーするのではない) * 関数の中でmodelとiterの内容が書き換えられる */ gtk_tree_selection_get_selected (selection, &model, &iter); /* 各コラムの値をListStoreからそれぞれ取り出して書き込む */ gtk_tree_model_get (model, &iter, COLUMN_A, &ret_a, COLUMN_B, &ret_b, -1); p = gdk_pixbuf_get_pixels (GDK_PIXBUF (ret_b)); /* それぞれを端末に表示 */ g_print ("A:%d\nB:\n", ret_a); n_channels = gdk_pixbuf_get_n_channels (GDK_PIXBUF (ret_b)); width = gdk_pixbuf_get_width (GDK_PIXBUF (ret_b)); height = gdk_pixbuf_get_height (GDK_PIXBUF (ret_b)); /* GdkPixbufオブジェクトの中の各ピクセルの色を取得 */ for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { r = p; g = p + 1; b = g + 1; /* * a = b + 1; * 今回のデータではアルファチャンネルの値は0 */ g_print ("[#%02x%02x%02x]", *r, *g, *b); p += n_channels; } g_print ("\n"); } g_print ("\n"); /* オブジェクトはg_object_unref()で参照カウンタを減らす */ g_object_unref (ret_b); } int main (int argc, char **argv) { GdkPixbuf *pixbuf1, *pixbuf2, *pixbuf3; GtkListStore *ls; GtkWidget *mainwindow, *menubar, *tv, *sw, *button, *vbox; GtkWidget *item_quit, *item_file, *menu_file; GtkAccelGroup *accelgroup; GtkTreeIter iter; GtkTreeViewColumn *col_a, *col_b; gtk_init (&argc, &argv); mainwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); /***** ショートカットキー(アクセラレータ) *****/ accelgroup = gtk_accel_group_new (); gtk_window_add_accel_group (GTK_WINDOW (mainwindow), accelgroup); /***** メニュー項目 *****/ item_quit = gtk_image_menu_item_new_from_stock (GTK_STOCK_QUIT, accelgroup); menu_file = gtk_menu_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu_file), item_quit); item_file = gtk_menu_item_new_with_mnemonic ("_File"); gtk_menu_item_set_submenu (GTK_MENU_ITEM (item_file), menu_file); menubar = gtk_menu_bar_new (); gtk_menu_bar_append (GTK_MENU_BAR (menubar), item_file); /***** 画像(GdkPixbuf) *****/ pixbuf1 = gdk_pixbuf_new_from_xpm_data (xpm1); pixbuf2 = gdk_pixbuf_new_from_xpm_data (xpm2); pixbuf3 = gdk_pixbuf_new_from_xpm_data (xpm3); /***** ツリービュー *****/ /*** コラム ***/ /* 最初の2つの引数は表示文字列とセルレンダラオブジェクト */ col_a = gtk_tree_view_column_new_with_attributes ("Column A", gtk_cell_renderer_text_new (), /* 「[セルレンダラのGObjectプロパティ名], [コラム番号]」の繰り返し */ "text", COLUMN_A, NULL); /* 最後にNULL */ col_b = gtk_tree_view_column_new_with_attributes ("Column B", gtk_cell_renderer_pixbuf_new (), "pixbuf", COLUMN_B, NULL); /*** データ(ListStore) ***/ ls = gtk_list_store_new (NUM_COLUMNS, G_TYPE_INT, G_TYPE_OBJECT); /*** ツリービューとその設定 ***/ tv = gtk_tree_view_new_with_model (GTK_TREE_MODEL (ls)); /* モデルと関連付け */ gtk_tree_view_append_column (GTK_TREE_VIEW (tv), col_a); gtk_tree_view_append_column (GTK_TREE_VIEW (tv), col_b); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tv), TRUE); sw = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add (GTK_CONTAINER (sw), tv); /* * ListStoreへのデータの追加 * 今回 * (192, pixbuf1), (168, pixbuf2), (1, pixbuf3) * という3つのデータを続けて追加するものとする */ gtk_list_store_append (ls, &iter); gtk_list_store_set (ls, &iter, COLUMN_A, 192, /* コラム番号と値のペア(引数2つ単位) */ COLUMN_B, pixbuf1, -1); /* -1を最後に付ける */ gtk_list_store_append (ls, &iter); gtk_list_store_set (ls, &iter, COLUMN_A, 168, COLUMN_B, pixbuf2, -1); gtk_list_store_append (ls, &iter); gtk_list_store_set (ls, &iter, COLUMN_A, 1, COLUMN_B, pixbuf3, -1); /***** ボタン *****/ button = gtk_button_new_with_mnemonic ("_Get"); /***** 垂直ボックス(縦方向分割) *****/ vbox = gtk_vbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); /***** ウィンドウ *****/ gtk_container_add (GTK_CONTAINER (mainwindow), vbox); gtk_widget_show_all (mainwindow); gtk_widget_set_size_request (mainwindow, 150, 150); gtk_window_resize (GTK_WINDOW (mainwindow), 170, 170); /***** シグナル *****/ g_signal_connect (G_OBJECT (mainwindow), "delete-event", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect (G_OBJECT (item_quit), "activate", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect_object (G_OBJECT (button), "clicked", G_CALLBACK (on_button_clicked), G_OBJECT (tv), G_CONNECT_SWAPPED); /***** メインループ開始 *****/ gtk_main (); return EXIT_SUCCESS; }
この例では
コラムBはGdkPixbufの画像となり、ボタンを押すと
A:192 B: [#000000][#000000][#000000][#000000][#000000][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#000000][#000000][#000000][#000000][#000000] [#000000][#000000][#000000][#000000][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#000000][#000000][#000000][#000000] [#000000][#000000][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#000000][#000000] [#000000][#000000][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#000000][#000000] (中略) [#000000][#000000][#000000][#000000][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#000000][#000000][#000000][#000000] [#000000][#000000][#000000][#000000][#000000][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#ff6666][#000000][#000000][#000000][#000000][#000000]
のように各ピクセルの色が順に端末に表示される。
関連記事:
- C言語でGTK+ 2を扱う上での幾つかのメモ(第3回) - 型の変換に関する内容を含む
- C言語でGTK+ 2を扱う上での幾つかのメモ(第7回) - GdkPixbufと参照カウンタ操作に関する例
- C言語でGTK+ 2を扱う上での幾つかのメモ(第8回) - ListStore/TreeViewに関するメモ
- C言語でGTK+ 2を扱う上での幾つかのメモ(第9回) - ListStore/TreeViewに関する例
- C言語のGTK+でListStoreからデータを取り出す処理に関する追加メモ(前半)
参考URL: