|
楼主 |
发表于 2004-3-9 13:08:05
|
显示全部楼层
这是我翻译的 FAQ.
水平不行, 第一次翻译, 希望大家不吝指正 :-)
时间不多, 只能一点一点得来, 见谅
:-)
gtkmm FAQ
摘要
这里是一些关于 gtkmm 的最常见的问题. 如果你的问题不在这里, 请电邮至 gtmmm 邮件列表. 如要你想把它加入到这份 FAQ, 请给这份文件打一个补丁 (gtkmm-faq.xml) 或者只是将你的建议提交到邮件列表.
1. gtkmm 在全世界的位置
1.1 什么是 GTK+ ?
GTK+ 是个 GUI(图形用户接口) 组件工具集, 用 C 写成. 它是 GNOME 项目的基础, 同时也是单独的应用程序. gtkmm 就建立在 GTK+ 的基础上. 具体看 http://www.gtk.org .
1.2 什么是 gtkmm (以前的名字叫 Gtk--) ?
gtkmm 是 GTK+ 的一个 C++ 封装. 也就是一种语言的绑定, 让你可以用 C++ 写 GTK+ 的程序. 它还包括对 C++ 特性的支持, 比如说继承, 多态以及 C++ 程序员们希望使用的其它一些功能强大的技术.
1.3 为什么命名为 gtkmm ?
gtkmm 原来的名字是 gtk--, 因为 GTK+ 的名字中已经含有一个 + 号. 但是, 对搜索引擎来说, 索引 -- 符号不太容易, 所以最后被定名为 gtkmm, 而且我们将一直使用它.
1.4 为什么要用 gtkmm 而不是 GTK+ ?
1. gtkmm 允许你写代码时使用通常的 C++ 的技术, 比如, 封装, 派生, 和多态. 作为一个 C++ 程序员, 你可能已经意识到这会导致更清晰的, 更好组织过的代码.
2. gtkmm 更加类型安全, 所以一些以前用 C 写的, 只能在运行期检查出来的错误
, 现在可以在编译期被检查出来. 这些特定的型别还使 API (应用程序接口) 更加清晰, 因为仅从方法的声明就可以看出应当使用什么类型.
3. 可以使用继承技术来派生新的组件. 在 GTK+ 中, 用 C 代码来派生新的组件太复杂了, 而且极易犯错, 所以很少有 C 程序员这么做. 作为一个 C++ 程序员, 你明白, 派生是一项重要的面向对象技术.
4. 可以使用成员变量, 从而简化内存管理. 所有的 GTK+ 的 C 组件都是用指针来处理的. 作为一个 C++ 程序员, 你明白, 只要可能, 就应当避免使用指针.
5. 更少的代码. GTK+ 的 C 对象模型使用带前缀的函数名称和转换宏. 例如:
gtk_button_set_text(GTK_BUTTON(button), "sometext");
gtkmm 的 C++ 代码更短, 而且更清晰. 例如:
button.set_text("sometext");
6. 不必担心 GTK+ 中不一致的引用记数策略.
1.5 为什么要用 libsigc++ ? 就用通常的 GTK+ 信号处理函数不行么?
1. GTK+ 的信号不是类型安全的, 所以编译器并不能告诉你, 是否你的回调函数的参数的个数, 类型或者返回值有错.
2. 他们只能作为全局函数或者静态方法来使用. 使用 libsigc++ 的支持, 回调函数可以被设计为成员方法, 可以使用特定物件的成员变量. 它们还可以被设计为虚函数, 你可以在派生类中再改写它们.
1.6 为什么 GTK+/GNOME 本身不用 C++ 写?
1. C 是一种比较简单的语言, 更多的人对之更熟悉一点, 尤其是在 Unix 平台上.
2. C 可以被其它任何语言包装, 使 API 为更多的开发者而用.
3. GTK+ 和 GNOME 的 C 代码被很好的组织过, 比我们遇到过的大多数 C 代码都要清晰得多. 这部分得益于基于 C 的面向对象的设计结构.
1.7 既然这么喜欢 C++, 用Qt不就行了么?
gtkmm 的开发者们之所以选择 gtkmm 而不是 Qt, 原因在于, gtkmm 按照更地道的 C++ 行为哲学来行事. Qt 产生于 C++ 和(准)标准库还没有被标准化的时候, 而且不能被编译器很好地支持. 它重复了如今标准库中的许多工作, 比如容器和类型信息. 更重要的是, 它修改 C++ 语言以实现信号功能, 所以, Qt 类很难被其它非 Qt 类使用. 而 gtkmm 不对 C++ 语言作任何修改, 仍可以使用标准 C++ 来实现信号操作.
1.8 Inti 和 gcode 怎么样?
Inti 是 RedHat 发起的一个项目, 旨在建立一个高度集成的 C++ 编程框架, 使客户程序员的们合作更加方便, 这个项目将由 RedHat 来领导. 在其它的事情中, 将建立一个 GTK+ 的 C++ 绑定. 这个绑定跟 gtkmm 有点类似, 但是功能要弱些. Init 没有发布任何版本, 尽管一些代码已经存在于 CVS 中了. 这个项目中断于这里. 现在, Inti 这个名字已经被一个原来名称为 gcode 的项目采用了.
GCode/Inti 似乎从原来的 Inti 那里继承了一些代码, 又似乎在追随 gtkmm2. 从我们所能告诉你的程序来说, 仅有的区别在于, GCode 使用了更少的 C++ 技术, 它更偏向于暴露更多的 GTK+ 的 C API. 目前, gcode/init FAQ 对于 gtkmm 作出了错误的建议 - 具体请看关于 STL-styled interfaces 和 C types 的问题. 而且, gcode/init 强制使用一种内存管理策略, 这种策略等同 gtkmm 中的 Gtk::manage() 特性, 在 gtkmm 中, 它是可以选用的. 这种强制使用的作法, 限制了程序员们发挥 C++ 内存管理技术的全部功能.
我们不明白, 作者为什么要展开这样一个单独的秘密的项目, 他不能换一种帮助 gtkmm 社区的作法么?
2. gtkmm 好在什么地方?
2.1 它运行在什么系统上?
只要编译器和库都是正确安装的, gtkmm 可以运行在任何类 UNIX 的系统上. GNU C++ 编译器和它的一组工具(也可以在 Linux 和 *BSD 系统上找到它们)构成了它的缺省编译环境.
gtkmm 也可以由下列工具编译:
1. Sun 的 Forte C++, 在 Solaris 平台上.
2. 在 Windows 平台上, 用 mingw 工具编译.
2.2 它有多完整?
就版本 1.2.x 而言, gtkmm 处理大部分(如果不是全部的话)由 GTK+ 1.2.x 版本系列提供的功能. 这意味着, 你可以用 gtkmm 完成任何 GTK+ 支持的工作. 如果还有什么部分没有被覆盖到, 希望能通知我们.
2.3 gtkmm 支持 C++ 所有的优点么? 比如说继承, 多态等等.
是的. gtkmm 对象对是普通的 C++ 对象, GTK+ 的继承也是通过 C++ 的继承实现的. 对其它任何 C++ 对象可行的操作, 对 GTK+ 对象同样可行.
2.4 gtkmm 使用标准 C++ (STL) 容器么? 比如说 std::string 和 std::list?
是的. 只要可能, 我们将坚定不移地重用标准 C++ 的代码. 开始的时候, 这可能并不太明显, 因为:
1. gtkmm 使用 Glib::ustring, 它和 std::string 有几乎相同的接口, 因为 C++ 标准并不支持 UTF-8 编码的字符串.
2. gtkmm 使用类似 Glib:IstHandle<int> 这样的接口, 它可以被赋值给几乎所有的标准 C++ 容器, 比如 std::list 或 std::vector. 这些立即类别已经付诸使用, 但并没有被强制应用.
另外, 一些组件, 比如 Gtk::TreeView, 有一些和标准容器很类似的接口. 举例来说, 你可以在被选择的行中逐个迭带.
2.5 是否不论是否合适, 是否麻烦或实现不好, gtkmm 都强制 GTK+ 组件使用 STL 式的接口?
不, 我们并不强迫你. 我们主一些容器组件提供了 STL 式的接口, 允许你在子组件中逐个迭带, 但是还有附加的更简单的接口. 之所以这样做, 是因为我们认为使用 STL 式的接口时, 有时需要太多的代码去实现简单的工作. 但从另一方面来说, 有些人不论是否合适, 虔诚地偏爱 STL 式的代码. 你有选择的权利.
2.6 gtkmm API 是否使用 C 类型, 比如说结构体?
不. 我们把所有的参数包装成了 C++ 的类, 这些类使用 C++ 的内存管理. 如果你发现还有没有特别原因的 C 类型的参数, 希望能通知我们.
2.7 gtkmm 被用来写了些什么程序?
在 gtkmm 网站的 "其它资源" 页上, 查看应用程序列表.
2.8 gtkmm 和 Qt 相比而言怎么样?
1. gtkmm 使用纯 C++. Qt 还需要用到 C++ 的一些扩展, 而这需要 moc 预处理器的分析.
2. gtkmm 使用 std::string, std::list, std::vector, 迭带子等等. Qt 有它自己特定的容器.
3. 使用 gtkmm 时, 你可以使用 C++ 的内存管理方式. Qt 要求所有的组件作为指针来处理, 并且组件的删除交由父组件来处理.
4. gtkmm 的组件的安排更加简单. 在 Qt 中, 容器和布局是分开的类, 子组件必须被同时添加到它们两者中.
5. gtkmm 希望被设计出一个清晰的 API. Qt 类的经常依赖一些隐晦的功能, 这个由易混淆的重写过的构造函数.
2.9 你们是包装了所有的 GNOME API, 还有 GTK+?
我们已经在 gnomemm 中包装了 gnome-libs, 它可以提供额外的 GNOME 功能. 一些部分, 比如 gnome-vfs, 还有 Bonobo, 对它们的包装还不太成熟.
2.10 gtkmm 会"膨胀"么?
不. gtkmm 是一个瘦包装. 人们可能会惊讶于 gtkmm 压缩包的巨大的尺寸. gtkmm的压缩包之所以这么大, 是因为:
1. 它包含许多 HTML 文档 - 比如: 引用文档, 书, 还有这份 FAQ. 它还包了文档的 Docbook XML 源文件.
2. 它包含了 .hg/.ccg 源文件, 这些文件被用来产生 .h/.cc 的 C++ 源代码, 和其它一些将被形成的文件.
我们移植这些产生的源代码, 以消除编译 gtkmm 时的各种依赖关系, 也使你的工作更加简单.
3. 更多的信息
3.1 有 gtkmm 的邮件列表么?
是的. 具体请看订阅页.
3.2 关于 gtkmm, 都有些什么文档?
有一份相当全的教程, 自动产生的引用文档, 这份 FAQ, 还有一些在文档页上可以运行的例子.
3.3 我在哪里可以找到例子代码?
看一下 gtkmm 发行版本的例子文件夹. 那里有一些第三方的应用程序, 你可以调试一下这些源代码.
4. 使用 gtkmm
4.1 编译 gtkmm 程序时, 我应当使用哪些编译器参数?
对于 gtkmm 2, 你应当使用 pkg-config. 例如:
pkg-config gtkmm-2.0 --libs --cflags
你应当在你的 configure.in 中使用 pkg-config 的 PKG_CHECK_MODULES 宏, 就像在 gtkmm_hello 例子所演示的那样.
4.2 我的程序报错找不到 libgtkmm.so 文件.
这是关于运行 GTK+ 程序被问及最多的单独问题, 我们在这里给一个解答, 尽管它已经在 GTK+ FAQ 里. 确定 /usr/local/lib (gtkmm的缺省安装路径) 在你的 /usr/ldconf 里被正确设置, 或者在存在于你的 LD_LIBRARY_PATH 里.
换个方法, 在执行 configure 的时候指定另一个前缀. 比如, 在 RedHat 上, 你可以这么做: ./configure --prefix=/usr
4.3 如何编译一个静态的可以执行文件?
gtkmm 在许多 linux 发行版上会被预先安装, 所以你不并不需要亲自来做, 但是你可以这样重新配置你的 gtkmm :
./configure --enable-static
make
make install
4.4 如何从 gtkmm 对象得到一个 GTK+ 对象?
如果你需要一些 gtkmm 不支持的 GTK+ 功能, 你可以调用 Gtk::Widget::gtkobj() (在 gtkmm2 里是 gobj()), 这将返回一个指向平常的 C GTK+ 数据结构. 你可以直接操作这个 C 对象, 就像在任何 GTK+ 程序里做的那样.
4.5 如何将 GTK+ 对象包装到一个 gtkmm 实例中?
Glib::wrap() 会返回一个指向 gtkmm 对象的指针. 这是一个重载函数, 所以它会给你一个恰当类的实例.
4.6 在 gtkmm 中可以使用 C++ 异常么?
是的, 可以, 但这并不是一个好主意. 官方的回答是, 既然平常的 C 不知道 C++ 的异常是什么, 在你的函数调用栈里, 只要抛出器和捕捉器之间没有 C 函数, 你就可以在你的 gtkmm 代码里使用异常. 这意味着你必须局部地捕捉自己抛出的异常.
在 gtkmm2 中情况有所改善 - 对于运行期间没有被捕捉的异常, 你会得到一个警告. 并且你可以对于未被捕捉的异常, 你可以指定自己的不同的处理句柄. 一些 gtkmm 方法甚至使用异常来报告错误. 这些将被抛出的异常类型在这些方法的引用文档里已经列出.
4.7 如何将 Glade 和/或 libglade 与 gtkmm 配合使用?
1. 当使用 Glade-- 时, Glade 可以输出 C++ 代码而不是 C 代码.
2. libglademm, gnomemm 的一部分, 包装了 libglade. 它允许你在运行期装载组件排列.
4.8 Gtk::manage(widet) 是做什么用的?
- 意思是 "容器组件将负责删除这个组件." 一些人喜欢用它, 因为他们再也不必为组件的删除而操心了. 只有当你用 add() 方法添加一个组件到容器组件中的时候, 才能使用 Gtk::manange().
4.9 我应当如何学习安排组件? 我被包装参数搞晕了.
使用 Glade 来处理 GTK+ 和 GNOME 组件是一个很棒的方法. 使用 Glade 去探究组件的选择, 看看它们是怎么被组合到一块儿的. 然后,在你的构造函数里和 add() pack() 方法里, 可以使用相同的设置和相同的参数. 或者你可以使用 libglademm 在执行期加载 GUI .
4.10 我习惯使用 MFC. 文档和视图在哪里? 或者我该如何使用文档/视图结构? 我该如何使用 MVC 模式?
1. 文档/视图(MVC模式一个非常有用的版本) 并不被 GTK+ 直接支持, 尽管它经常被 GTK+ 程序员们使用. 这种情况在 gtkmm2 中得到了改善, 新的文本控件和树形控件接口被切分成了模型和视图.
2. Bakery 库可以使 gtkmm/gnomemm 的 C++ 程序员们非常容易地使用文档/视图框架.
4.11 使用 gtkmm 时, 如何加载位图?
使用 Gdk:ixbuf 和 Gtk::Image. 两者都易于使用, 并且通过 pixbuf 插件可以支持大量的图形文件类型.
4.12 gtkmm 是线程安全的么?
Paul Davis 写道:
不论是 X, GDK 或者 GTK+ 又或是 gtkmm, 从它们本身来说, 都是线程安全的. 你要么使用 gdk_threads_{enter, leave}() 函数来保护所有的 GDK/GTK+/gtkmm 函数, 要么你就得确定你只有一个线程在作这些调用. 一个通常使用的作法是用一个非 GUI 线程通过管道向 GUI 线程发送请求 . 这个管道使用钩子技术挂在 GTK 使用的 glib 的主消息循环上.
就个人来讲, 我从来只用一个线程的那种作法, 我发现它很适合我的程序.
注意, glibmm (在 gtkmm2 里) 里有 Glib:ispatcher, 它使用上面提到的管道技术, 实现了线程间的信号处理.
Andress Rottmann 写道:
如果你需要一个线程间非常复杂的消息传递方法, 看一下 libsigc++ extras. 它在 libsigc++ 的基础上, 提供了线程间的, 类型安全的信号槽调用, 和它一起的还有一个 gtkmm 例子.
4.13 为什么在 gtkmm 里使用 dynamic_cast<> 时, 我的程序发生的段错误?
gcc 2.96 以及更早一些的版本有一个 bug, 导致不能在构造函数中使用 dynamic_cast<>. 当你从 gtkmm 类派生出一个类, 并且指定一个特定的构造函数时, 这将成为一个问题. 你可以通过使用不同的构造函数的办法来避免这个问题. 比如, 你可以不用 Gtk::Button("sometext") 这个构造函数, 而是使用一个缺省的构造函数, 再用 Gtk::Button::set_label() 方法. 要得到更多信息, 请看这个 bug report. 这个 bug 并不是影响所有的非缺省构造函数 - 如果你正在使用一个老版本的编译器, 你可以试试看.
|
|