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

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

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

C言語でGTK+ 2を扱う上での幾つかのメモ(第7回)」の続き。

ListStoreに対するデータの出し入れとツリービュー関係の操作

ツリービューなどで表示するデータとして用いるListStoreというデータ構造に対するデータの出し入れの形がC言語やVala言語ではPyGTKとは異なる。
ListStoreはイメージとしては構造体をデータ(中身)とするリスト構造に近く、各データには複数の値を持たせることができ(型は順番ごとに固定)、リストのようにデータの追加や削除などが行える。このデータはツリービューやコンボボックスといったGUI部品と関連付けてその内容を表示するようにできる。内部的にはGUI部品などと同様のGObjectオブジェクト。

ListStoreオブジェクトの作成

ListStoreオブジェクトを作成するにはgtk_list_store_new()を呼び、最初の引数にコラム数,その後ろにはコラムの数だけ型を指定するマクロ(G_TYPE_[型名])を指定する。型はgint64のようなbit数を保証しているもの(例:G_TYPE_INT64)を用いることもできる。

enum
{
  COLUMN_A,
  COLUMN_B,
  COLUMN_C,
  NUM_COLUMNS,
};

...

/* この場合、それぞれのデータが(真偽値, 整数, 文字列)の3つの値をまとめて持つことになる */
GtkListStore *ls = gtk_list_store_new (NUM_COLUMNS,
                                       G_TYPE_BOOLEAN,
                                       G_TYPE_INT,
                                       G_TYPE_STRING);
ツリービューコラムとセルレンダラ

ツリービューのコラムのオブジェクトの作成にはgtk_tree_view_column_new_with_attributes()を用い、引数が「コラム名,セルレンダラオブジェクト,(セルレンダラのGObjectプロパティ名と対応するコラム番号の繰り返し),NULL」となっているものの、要領はPyGTKと同様で、ツリービューへの追加の要領も同様。

GtkTreeViewColumn *col_a, *col_b, *col_c;
GtkListStore *ls;
GtkWidget *tv;
/* 最初の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 = [略] ;
ls = gtk_list_store_new ( [略] );
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);
ListStoreにデータを入れる

PyGTKでは言語バインディングの親切機能によりPythonのタプルという形でデータを追加することができたが、C言語では

  1. 追加後のデータを入れる場所を指し示すためのGtkTreeIter型構造体を用意(宣言する)
  2. 追加用の関数(gtk_list_store_append()など)を呼ぶとGtkTreeIter型構造体に場所が設定される
  3. 受け取った場所を指定してデータ書き込み用の関数(gtk_list_store_set()など)を呼び、そこへデータを書き込む

といった流れで作業を行う。Vala言語でも内部的にはC言語GTK+のコードを生成することになり、要領もこれに同じとなる。

データを取り出す

C言語におけるListStoreからのデータの取り出しは多少面倒。
まずは取り出したい項目を指し示すGtkTreeIter型構造体を宣言しておき、「gtk_tree_model_get_iter*」系関数や、それにより得たものを「gtk_tree_model_iter*」系関数で動かしたものを用意し、これとListStoreにおける取り出したいコラム番号をGtkTreeModelインターフェースのgtk_tree_model_get_value()などに渡すことで中の個別のコラムのデータが取り出せる。
しかし、この関数への引数として渡すのはGValueという型へのポインタとなっており、下のような形でデータを確保する。

GValue *val = g_new0 (GValue, 1);

この後gtk_tree_model_get_value()などを呼び、中にデータが入った後は、GObjectライブラリ内のg_value_get_[型名]()の関数でそれぞれの型としてのデータを得ることになる。例えば、取り出したいデータのコラムが(g)int型の場合は

gint val_int = g_value_get_int (val);

のようにして取り出す(ListStore上で決めた型と一致する必要がある)。型はGLibが用意する様々な型に対応しており、もちろん(g)int64などの「環境によらずbit数を保証する」類の型も利用できる。
なお、データは動的に確保されたものなので、後で手動で解放する必要がある。

g_free (val);

Vala言語ではGLib.Value型構造体を用いるが、この構造体のget_int()などのメンバ関数を用いて型を指定して取り出すことになる。データの解放は構造体変数の寿命とともに自動的に行われる。

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

関連記事:

参考URL: