リスト


GTK+では昔、Listウィジェットが使われ、Visual Basicのリスト・ツールのように使えていたらしい。 GTK+2.0以降は、TreeViewウィジェットが代わりに用いられるようになった。 サンプルが有った。

#include <gtk/gtk.h>

//Model の定義
void create_model(GtkWidget *treeview)
{
  GtkListStore *store;

  //GtkListStore の生成、および列定義
  store = gtk_list_store_new(
    4,
//要素の個数

    G_TYPE_STRING,
//名前

    G_TYPE_STRING,
//クラス

    G_TYPE_INT,
//最高得点

    G_TYPE_INT
//最低得点

  );

  //treeview に結びつける
  gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(store));

  //一旦結びつけたらstore自体は開放してよい
  g_object_unref(store);
}

//Modelに実データ追加
void set_data(GtkWidget *treeview)
{
  GtkListStore *store;
  GtkTreeIter iter;

  //treeviewに結びつけられているModelを取得する。
  //一旦、中のデータをすべて消去する。
  store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)));
  gtk_list_store_clear(store);

  //新しいレコード(3つ)を生成する
  gtk_list_store_append(store, &iter);
  gtk_list_store_set(store, &iter,
    0, "Taro",
//名前

    1, "A",
//クラス

    2, 78,
//最高得点

    3, 36,
//最低得点

    -1);
//終端


  gtk_list_store_append(store, &iter);
  gtk_list_store_set(store, &iter, 0, "Jiro", 1, "B", 2, 67, 3, 45, -1);

  gtk_list_store_append(store, &iter);
  gtk_list_store_set(store, &iter, 0, "Saburo", 1, "C", 2, 81, 3, 51, -1);
}

//treeviewに列を1つ追加
void append_column_to_treeview(GtkWidget *treeview, const char *title, const int order)
{
  GtkTreeViewColumn *column;
  GtkCellRenderer *renderer;

  //CellRendererの作成
  renderer = gtk_cell_renderer_text_new();

  //列を作成し、CellRendererを追加する。さらにModelとの関連を定義する
  column = gtk_tree_view_column_new_with_attributes(
    //ヘッダ行に表示するタイトル
    title,
    //CellRenderer
    renderer,
    //Modelのorder番めのデータを、rendererの属性"text"に結びつける
    "text", order,
    //終端
    NULL
  );

  //生成した列を、元のtreeviewに追加する
  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
}

//treeviewにViewを定義する
void create_view(GtkWidget *treeview)
{
  append_column_to_treeview(treeview, "名前", 0);
  append_column_to_treeview(treeview, "クラス", 1);
  append_column_to_treeview(treeview, "最高得点", 2);
  append_column_to_treeview(treeview, "最低得点", 3);
}

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

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "成績表");
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

  //GtkTreeViewの生成
  treeview = gtk_tree_view_new();

  //Modelの定義
  create_model(treeview);

  //Modelに実データ追加
  set_data(treeview);

  //Viewの定義
  create_view(treeview);

  gtk_container_add(GTK_CONTAINER(window), treeview);
  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}


TreeViewウィジェットは階層を持てるリスト表示なので、奥が深い。 ここでは階層の無いGtkListStoreに列要素を定義し、 GtkTreeIter構造にデータを格納して行く。 また、列と行を持つ表としてデータを処理するするため、GtkCellRendererオブジェクトを使う。 最後にリストのデータを行として表示するのに、GtkTreeViewColumnも使う。 サンプルでは、 "名前"、"クラス"、"最高得点"、"最低得点"の4つのデータを持った行を表示する。

gtk_tree_view_column_get_title() という物がマニュアルに載っていたので、何を出力するか試してみた。

#include <gtk/gtk.h>

static void cb_button2_clicked (GtkWidget *button, gpointer user_data)
{
  const gchar *text;
  char buf[256];
  text = gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(column));
  g_print( "%s\n", text );
  sprintf(buf, "%s", text);
  gtk_label_set_text(GTK_LABEL(label), text);
}

static void cb_button1_clicked (GtkWidget *button, gpointer user_data)
{
  gtk_main_quit();
}

void create_model(GtkWidget *treeview)
{
  GtkListStore *store;
  store = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
  gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(store));
  g_object_unref(store);
}

void set_data(GtkWidget *treeview)
{
  GtkListStore *store;
  GtkTreeIter iter;

  store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)));
  gtk_list_store_clear(store);

  gtk_list_store_append(store, &iter);
  gtk_list_store_set(store, &iter, 0, "Taro", 1, "A", 2, 78, 3, 36, -1);

  gtk_list_store_append(store, &iter);
  gtk_list_store_set(store, &iter, 0, "Jiro", 1, "B", 2, 67, 3, 45, -1);

  gtk_list_store_append(store, &iter);
  gtk_list_store_set(store, &iter, 0, "Saburo", 1, "C", 2, 81, 3, 51, -1);
}

void append_column_to_treeview(GtkWidget *treeview, const char *title, const int order)
{
  GtkCellRenderer *renderer;
  renderer = gtk_cell_renderer_text_new();
  column = gtk_tree_view_column_new_with_attributes( title, renderer, "text", order, NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
}

void create_view(GtkWidget *treeview)
{
  append_column_to_treeview(treeview, "名前", 0);
  append_column_to_treeview(treeview, "クラス", 1);
  append_column_to_treeview(treeview, "最高得点", 2);
  append_column_to_treeview(treeview, "最低得点", 3);
}

int main(int argc, char **argv)
{
  GtkWidget *window, *button1, *button2, *vbox1, *vbox2, *hbox, *frame;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_widget_set_size_request(window, 300, 200);
  gtk_window_set_title(GTK_WINDOW(window), "成績表");
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
  treeview = gtk_tree_view_new();
  create_model(treeview);
  set_data(treeview);
  create_view(treeview);

  vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
  vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
  //Frameウィジェットを作成
  frame = gtk_frame_new("Frame");
  //Frameの枠のタイプを指定
  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
  gtk_container_add(GTK_CONTAINER(frame), vbox2);
  gtk_box_pack_start(GTK_BOX(vbox2), treeview, TRUE, TRUE, 0);
  button2 = gtk_button_new_with_label("Output");
  gtk_box_pack_start(GTK_BOX(vbox2), button2, TRUE, TRUE, 0);
  g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(cb_button2_clicked), NULL);
  label = gtk_label_new("blank");
  gtk_box_pack_start(GTK_BOX(vbox2), label, TRUE, TRUE, 0);
  gtk_container_add(GTK_CONTAINER(window), vbox1);
  gtk_box_pack_start(GTK_BOX(vbox1), frame, TRUE, TRUE, 0);
  button1 = gtk_button_new_with_label("Quit");
  gtk_box_pack_start(GTK_BOX(vbox1), button1, FALSE, FALSE, 0);
  g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK(cb_button1_clicked), NULL);
  gtk_container_set_border_width(GTK_CONTAINER(frame), 10);
  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

ウィジェットのタイトルを取得してラベルに出力してみると、3項目いずれを指定しても「最低得点」だった。 できれば、リストの文字列を取り出したいが、TreeViewを更に学ばなければいけないようなので、 後回しにする。 フレーム・ウィジェットに触れてみた。枠の表示につて、もう少し触れたいと思うが、 長くなったので次章にする。


前章  | 目次 |  次章



トップ



/