在GTK+的所有构件(widget)中,GtkTreeView算是比较难的一个了,做一个完整的GtkTreeView要牵涉到不少其他的构件或对象,对于初次使用GtkTreeView的朋友来说,可能有点难度,因此我就我所知道的结合GTK+ API手册来给初来乍到的朋友略讲一下。希望对正在使用Gtk+的朋友有所帮助。

这是测试程序执行的界面:

下面我们就来讲解如何使用GtkTreeView构件

一、MVC

首先应该介绍的是MVC这个模式,Model/View/Controller(模式/视图/控制器),GtkTreeView就是按照这样的结构来设计的。这样的好处是,让数据和视图进行分离,同一份数据可以设计不同的视图来显示。如同一份数据,我可以在一个界面中用条状图来显示,同时又可以用曲线来显示。当你更新你的数据的时候,视图就会自动更新来显示你的数据变化,所以这部分工作就是控制器来完成的了。之所以要讲MVC设计模式的原因就是,我们的GtkTreeView构件就是这么来设计的。所以先了解了这个再来学GtkTreeView,理解就容易多了。

二、GtkTreeView的组成

上面我都说了,要使用GtkTreeView要牵涉到其他不少的构件或对象,因此下面我们就来看一下在使用GtkTreeView时我们一共需要哪些构件或对象:
1,GtkTreeView – 树视图
2,GtkTreeViewColumn – 列视图
3,GtkCellRenderer – 渲染器
4,GtkTreeModel – 树模式(树状or链表)

三、创建一个树视图

3.1 第一步:创建一个模式

Gtk+提供了两种简单的模式,一个是GtkListStore,一个是GtkTreeStore。如果你对模式理解还有一些困难的话,其实我们完全可以简单的将GtkListStore和GtkTreeStore理解成数据库,它们就是存放我们数据的地方。一个是存放链式的数据,一个是存放树状的数据。我们可以通过下面的函数来创建一个模式(数据库);

GtkListStore *store;
store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_BOOLEAN);

这个函数创建一个了一个链式的模式,这个链表具有两列。它们分别具有字符串类型和布尔类型,典型的用法我们是不会直接使用2来标明这个链表的列数的。我们根据Gtk+api手册提供的方法,创建一个模式更好的方法是按照下面的方式来创建:

enum{
    MYID_COLUMN,
    TITLE_COLUMN,
    AUTHOR_COLUMN,
    STATUS_COLUNM,
    NBR_COLUMNS
};
store = gtk_list_store_new(NBR_COLUMNS,       /* NBR_COLUMNS = 4 */
                            G_TYPE_INT, 
                            G_TYPE_STRING,  
                            G_TYPE_STRING, 
                            G_TYPE_FLOAT); 

3.1 第二步:向模式(数据库)中添加数据

当我们创建好了我们的模式之后,我们就可以向其中添加数据了,我们可以通过下面的函数和方法来向我们的模式中添加数据:

GtkTreeIter         iter;    /* 迭代器 */
gtk_tree_store_append(store, &iter, NULL);   /* 获取插入的位置 */
gtk_tree_store_set(store, &iter,
                    MYID_COLUMN, 1,
                    TITLE_COLUMN, "美丽的大草原",
                    AUTHOR_COLUMN, "甲A",
                    -1);

注意:最后一个参数是-1,因为gtk_tree_store_set()这个函数是一个变参数函数,也就是说参数的个数可以改变的,因此需要一个-1来标志参数的结束。通过上面的语句我们就向模式中添加了一行数据了。可能你会问iter是做什么的,从字面以上我们可以读成“迭代器”,也正如它的意思(其实我们不用管那么多),不用知道GtkTreeIter内部结构是怎么样的,我们只需把它看作用来标志store的某一行的一个数据就可以了。通过gtk_tree_store_append这个函数,我们就得到了我们下一个可以插入数据的位置是什么了,iter就标志了这个位置。我们还可以继续通过这两个函数,不断的望模式中添加数据。在gtk_tree_store_append的第三个参数为NULL表示获取顶层的迭代器iter.我们也可以获取某一迭代器的迭代器。如:

gtk_tree_store_append (store, &iter1, NULL); /* 获取顶层的迭代器iter */
gtk_tree_store_set (store, &iter1,
TITLE_COLUMN, "我的分类1",
AUTHOR_COLUMN, "",
CHECKED_COLUMN, FALSE,
-1);

gtk_tree_store_append (store, &iter2, &iter1); /* 获取子迭代器 */
gtk_tree_store_set (store, &iter2,
TITLE_COLUMN, "我的标题1",
-1);

gtk_tree_store_append (store, &iter2, &iter1);
gtk_tree_store_set (store, &iter2,
TITLE_COLUMN, "我的标题2",
-1);
... 

这里我就没有编写子iter用法的列子了。关心的同学可以自己去查阅GTK+API手册,经过上面的讲解应该不难了

3.2 创建一个视图

当我们创建完成我们的模式(数据库)创建之后,我们就可以创建一个视图来显示它了。这就要用到我们的GtkTreeView视图了。

GtkWidget*     tree;
tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));

然后我们定义这个视图的列,我们需要用到一个 GtkTreeViewColumn 的对象了

GtkCellRenderer *renderer;/* 渲染器 */
GtkTreeViewColumn *column;

renderer = gtk_cell_renderer_text_new();
g_object_set(G_OBJECT(renderer), "foreground", "red", NULL);
column = gtk_tree_view_column_new_with_attributes("编号",
                                                    renderer,
                                                    "text", AUTHOR_COLUMN,
                                                    NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);

上面的几条语句就定义了一个列对象了,并且把这个列对象与模式的第MYID_COLUMN列联系起来了,然后我们将这个列添加到我们的tree视图中。按照同样的方式我们就可以添加其他更多的列了。

到了这一步我们也算了解了GtkTreeView的创建的过程了,最后我们再为每个行添加一个行选择信号处理函数就比较完美了。

3.3 添加行选择信号

大多数的应用程序不仅仅只需要处理显示数据就完成了,而且还需要获取用户的输入信号,为了达到这个目的,我们使用”changed”信号来与用户的选择信号进行关联起来。

/* changed信号处理函数原型 */
static void tree_selection_changed(GtkTreeSelection *selection, gpointer data);

/* 设置选择对象*/
GtkTreeSelection *select;

select = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
g_signal_connect(G_OBJECT(select), "changed",
G_CALLBACK(tree_selection_changed),
NULL);

三、总结

为了给上面的讲解有一个更加直观的了解,我为其写了一个简单的用例,在这个用例中,我设计了4列其他们之间完全没有任何的联系,只是为了给大家演示某种对象或控件的用法,例如我把”编号”列的字体设为了红色,是为了让大家了解“渲染器”的用法,给程序添加一个进度条,是为了给大家演示在GtkTreeView中进度条,该怎么使用,只要在加上一个计时器,进度条就可以动起来了。希望这篇文章对各位学习GtkTreeView的同学有所帮助,由于代码有点长度,因此没有列在文章中,但是在文章的开头我已经提供了下载源代码的连接。其中包含一个GtkTreeView.c的文件,和Makefile文件,以及一个已经编译过的可直接运行的GtkTreeView程序,如果点击不能运行,请修改该程序的属性以允许该程序执行。

代码预览:

注意:如果你要亲自编译,请确保你已经安装了Gtk库文件,安装方法sudo apt-get install libgtk+-2.0。如果安装不了,请换一个更新源。


作者:余强
从之前的内容来看,作者的博客地址可能是 http://www.sharej.com/topic/93044/ ,遗憾的是目前该网站已打不开了。