// 所有原创文章转载请注明作者及链接
// http://blog.csdn.net/blackboyofsnp/archive/2010/09/29/5913206.aspx
// blackboycpp(AT)gmail.com
// QQ群: 135202158
1. 背景
ethereal 0.2.0使用了GTK+来实现界面, 然而, 由于GTK+的更新很快, ethereal 0.2.0所使用的GTK+版本(1.0.1)和目前的版本(比如, 我所用的2.16.6)已经很不一样了, 很多构件或函数已遭废弃(如GtkText和GtkTree已经被设计更好的GtkTextView和GtkTreeView所代替), 因此直接编译是会出错的. 我们必须修改源代码, 以使得编译通过.
2. 下载并安装GTK+2.0
可以到http://www.gtk.org/download.html去下载GTK+. 对于Windows用户, 为了简便, 可以下载所谓的”All-in-one bundles”版本, 这种版本除了GTK+, 还包括它所要用到的所有第三方程序包. 一键安装, 岂不快哉?
下载之后解压缩到某个目录,如x/gtk. 然后将x/gtk/bin加入到环境变量PATH. 之后, 打开CMD, 运行”pkg-config --cflags gtk+-2.0”, 如果正常, 应该显示和以下相似的内容:
-mms-bitfields -IX/gtk/include/gtk-2.0 -IX/gtk/lib/gtk-2.0/include -ID :/dev/gtk/include/atk-1.0 -IX/gtk/include/cairo -IX/gtk/include/pango- 1.0 -IX/gtk/include/glib-2.0 -IX/gtk/lib/glib-2.0/include -IX/gtk /include/freetype2 -IX/gtk/include -IX/gtk/include/libpng14
注意: X/gtk/是你将GTK+解压缩到的主目录.
运行”gtk-demo”, 则会打开自带的演示程序. 不光如此, 它还贴心地附带了大量的文档, 位置在X/gtk/share/gtk-doc/html/目录下. 方便了离线查阅.
3. 在Windows下练习GTK+的开发
我推荐用两种IDE来进行Windows下的GTK+开发. 一是Code::Blocks, 二是Dev-C++. 我强烈推荐用强大的Code::Blocks!!! 因为她太好用了, 以至我不需要写说明. 喜欢用Dev-C++的朋友可以参考我的这篇介绍: http://blog.csdn.net/blackboyofsnp/archive/2008/11/20/3343045.aspx 好了, 有了GTK+, 有了IDE, 是时候练习一些东西了. HelloWorld就不说了, 主要学习一下较新的GtkTreeView和GTextView构件.
3.1 GtkTreeView构件
GTK+中的这个构件用来实现LIstView和TreeView.
概述
在GTK+中, 使用GtkTreeModel接口和GtkTreeView构件, 可以创建树形或列表控件. 此构件采用了Model/View/Controller设计, 包含4个主要部分:
(1) Tree view构件(GtkTreeView)
(2) 视图列(GtkTreeViewColumn)
(3) 单元格[cell]呈现器(GtkCellRenderer等)
(4) 模型接口(GtkTreeModel)
视图由前3个对象组成, 最后一个是模型. MVC设计的一个主要优点是多个视图可以基于一个模型创建. 例如, 可以为文件管理器创建一个映射文件系统的模型. 这样, 就可以创建多个视图来显示文件系统的多个部分, 而只需要在内存中保存一份拷贝. 单元格呈现器的目的是为了给构件提供可扩展性, 并以多种方式呈现相同类型的数据. 考虑如何呈现一个布尔变量. 它应该以字符串”True”或”False”, “On”或 ”Off”, 还是以一个checkbox呈现?
创建一个model
GTK+提供两个简单可用的Models: GtkListStore和GtkTreeStore. GtkListStore用于列表构件, 而GtkTreeStore用于树形构件. 开发一个新的model类型也是可能, 但这两个基本已经够用了. 创建model很简单:
- GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
以上代码创建了有两个列的列表, 一个字符串列和一个布尔值列. 不过一般不直接传递2这样的字面参数; 通常使用一个enum来包含不同的列, 它的最后一项是列的总数. 下面的示例代码显示了这一点, 仅仅是用treeview代替了listview:
- enum
- {
- TITLE_COLUMN,
- AUTHOR_COLUMN,
- CHECKED_COLUMN,
- N_COLUMNS
- };
- GtkTreeStore *store = gtk_tree_store_new (N_COLUMNS, /* 列总数 */
- G_TYPE_STRING, /* 书名 */
- G_TYPE_STRING, /* 作者 */
- G_TYPE_BOOLEAN); /* 是否选中? */
要将数据添加到model, 需要使用gtk_tree_store_set()或gtk_list_store_set()函数. 另外还需要取得GtkTreeIter, 此迭代器指向数据将要被添加的位置. 请看以下示例:
- GtkTreeIter iter;
- gtk_tree_store_append (store, &iter, NULL); /* 取得迭代器 */
- gtk_tree_store_set (store, &iter,
- TITLE_COLUMN, "深入浅出HTML",
- AUTHOR_COLUMN, "某网友",
- CHECKED_COLUMN, FALSE,
- -1);
注意最后一个参数是-1, 这是因为gtk_tree/list_store_set()是一个可变参数的函数, 它需要知道何时停止处理参数. 它可以用于为一个给定行的任意或所有列设定数据.
gtk_tree_store_append()的第3个参数是父迭代器. 它用于向一个GtkTreeStore添加一行, 并做为已存在的行的子行. 这意味着此新行只有在它的父行可见并处于展开状态时. 请考虑以下的示例: