試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

C言語でGTK+ 2を扱う上での幾つかのメモ(第9回)

C言語でGTK+ 2を扱う上での幾つかのメモ(第8回)」の続きとして、C言語GTK+ 2のツリービュー(ListStore使用)のテストを行う例を貼り付ける。
[任意]ファイル名: treeviewliststoretest.c

#include <gtk/gtk.h>
#include <stdlib.h>

/*
 * C言語によるGTK+のTreeView(ListStore使用)のテスト
 *
 * gcc -O2 -Wall -Wextra $(pkg-config --cflags --libs gtk+-2.0) treeviewliststoretest.c -o treeviewliststoretest
 */

enum
{
  COLUMN_A,     /* 最初は0 */
  COLUMN_B,
  COLUMN_C,
  NUM_COLUMNS,  /* 最後のコラム番号の次がコラム数になる */
};

void
on_button_clicked (GtkTreeView *tv)  /* swapped指定なのでボタンではない */
{
  GValue *val_a, *val_b, *val_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);
  /* 取り出す値を入れる領域 */
  val_a = g_new0 (GValue, 1);
  val_b = g_new0 (GValue, 1);
  val_c = g_new0 (GValue, 1);
  /* 各コラムの値をListStoreからGValueにコピー */
  gtk_tree_model_get_value (model, &iter, COLUMN_A, val_a);
  gtk_tree_model_get_value (model, &iter, COLUMN_B, val_b);
  gtk_tree_model_get_value (model, &iter, COLUMN_C, val_c);
  /* それぞれを元の型として取り出し、端末に表示 */
  g_print ("A:%s B:%d C:%s\n",
           g_value_get_boolean (val_a) ? "TRUE" : "FALSE",
           g_value_get_int (val_b),
           g_value_get_string (val_c));
  /* g_new0()で確保したデータはg_free()で解放する */
  g_free (val_a);
  g_free (val_b);
  g_free (val_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;
}

実行すると縦方向に3つの項目があり

それぞれを選択した状態でボタンを押すとその内容が

(1つ目の項目を選択してボタンを押す)
A:FALSE B:12345 C:test
(2つ目の項目を選択してボタンを押す)
A:TRUE B:99999 C:GTK+
(3つ目の項目を選択してボタンを押す)
A:FALSE B:838861 C:ListStore

のように端末に表示される。

関連記事: