【探索wireshark】 熟悉GTK+

来源:互联网 发布:班车路线查询软件 编辑:程序博客网 时间:2024/06/09 05:45

// 所有原创文章转载请注明作者及链接
//
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很简单:

以上代码创建了有两个列的列表, 一个字符串列和一个布尔值列. 不过一般不直接传递2这样的字面参数; 通常使用一个enum来包含不同的列, 它的最后一项是列的总数. 下面的示例代码显示了这一点, 仅仅是用treeview代替了listview:

要将数据添加到model, 需要使用gtk_tree_store_set()或gtk_list_store_set()函数. 另外还需要取得GtkTreeIter, 此迭代器指向数据将要被添加的位置. 请看以下示例:

注意最后一个参数是-1, 这是因为gtk_tree/list_store_set()是一个可变参数的函数, 它需要知道何时停止处理参数. 它可以用于为一个给定行的任意或所有列设定数据.

gtk_tree_store_append()的第3个参数是父迭代器. 它用于向一个GtkTreeStore添加一行, 并做为已存在的行的子行. 这意味着此新行只有在它的父行可见并处于展开状态时. 请考虑以下的示例:

 

尽管可以选择多种不同的models, 但只需要一种view构件. 它可以用于listview或treeview模式. 使用GtkTreeView不难, 它需要GtkTreeModel来了解从哪里取得它的数据:

 

Columns和cell renderers

有了Model的GtkTreeView需要用columns和cell renderers来显示model.

cell renderers以某种方式绘制tree model中的数据. GTK+2.0有很多cell renderers, 包括GtkCellRendererText, GtkCellRendererPixbuf和 GtkCellRendererToggle. 写一个自定义的renderer也是比较简单的.

GtkTreeView用GtkTreeViewColumn对象来组织tree view中的纵向列. 它需要知道列的名字, cell renderer的类型以及向给定行显示哪些数据.

处理选中的项

大多数应用程序不仅要显示数据, 还接受来自用户的输入事件<如选中某个结点>. 要完成这个功能, 可以简单地取得选中项(selection)对象的引用, 并和”changed”信号连接:

 

然后, 在回调函数里取得选择行的数据:

一个完整而简单的示例


3.2 GtkTextView构件

概述

GTK+拥有一个非常强大的多行文本编辑框架. 主要的对象是GtkTextBuffer,它用来表示正在编辑的文本, 还有GtkTextView构件, 它用来显示GtkTextBuffer. 每个buffer可以被多个view显示.

GTK+中的文本都以UTF-8进行编码. 这意味着一个字符可以被编码为多个字节. 字符数通常称为offsets, 而字节数则称为indexes. 如果混淆了两者, 在 ASCII的情况下当然没事, 但只要你的buffer包含了多字节字符, 情况就糟了.

buffer里的文本可以由tags来进行标记. tag是一个可以用于一系列文本的属性. 例如, 一个名为”bold”的tag可以用来加粗一些文本. 然而, tag的概念比这个更宽泛, 它也不只是影响到文本的外观, 还可以影响鼠标或击键的行为, “锁定”文字以使用户不可以编辑, 等等等等. tag由GtkTextTag对象表示. 一个GtkTextTag可以用于多个buffer内的多项文本.

每个tag储存于GtkTextTagTable. 一个tag table定义了一套可以一起使用的tags. 每个buffer关联一个tag table; 只有来自tab table的tags才能被 buffer所使用. 然而, 单个tag table可以在多个buffer间共享.

tag可以有名字(如”bold”), 也可以没有.

大多数文本操作使用GtkTextIter表示的iterators来完成. iterator用来表示text buffer中两个字符之间的位置. GtkTextIter这个struct被设计为在stack上分配内存, 它保证可以被值拷贝, 并绝不包含任何heap上分配的数据. Iterator也不是一直有效的, 每当buffer被修改导致其中的字符数发生变化时, 先前的iterator就会失效. (注意: 删除5个字符, 再重新插入5个字符仍然会使iterator失效, 尽管最终的数目一样, 但状态已经改变了)

因此, 不能使用iterators在buffer修改时保存位置, 而应使用理想的GtkTextMark. 可以把mark看作一个不可见的光标或插入点, 它通过在buffer内浮动来保存位置. 如果包围mark的文本被删除, 此mark依然处于以前所占的位置; 如果在mark那里插入文本, mark会根据gravity来决定位于新文本的左边或右边. 从左向右读的语言的标准文本光标是一个gravity为右的mark, 因为它总是呆在插入文本的右边.

和tag一样, mark也可以有名或匿名. GtkTextBuffer有2个内建的marks: “insert”和”selection_bound”, 分别指插入点和不是插入点的那个选择项的边界. 如果没有选择文本, 那么这两个marks的位置相同.

text buffer通常至少包含一行, 但有可能是空的(即buffer可以包含0个字符). text buffer的最后一行绝不会以行分隔符结束(如newline); 其他行则以一个行分隔符结束. 在计算字符数和字符偏移时会算上行分隔符. 注意一些Unicode行分隔符在UTF-8中以多个字节表示, 2个字符序列”/r/n”也会被看成是1个行分隔符.

一个简单示例


1. Gtk+自带文档 X/gtk/share/gtk-doc/html/gtk/
2. GTK+初学者教程(中文) – 卢名杨译
http://zetcode.com/tutorials/gtktutorial/chinese/