[ 英文 ]

gtkmm 常见问题

gtkmm在世界中的地位

什么是 GTK+?

GTK+ 是个 GUI(图形用户接口) 组件工具集,用 C 写成。它是 GNOME 项目、以及许多其他单独的应用程序的基础。gtkmm 就建立在 GTK+ 的基础上。请看 http://www.gtk.org/。

什么是 gtkmm?

gtkmm 是 GTK+ 的一个 C++ 封装。也就是一种语言的绑定,让你可以用 C++ 写 GTK+ 的程序。它还包括对 C++ 特性的支持。比如说继承、多态以及 C++ 程序员们希望使用的其它一些功能强大的技术.

为什么命名为 gtkmm?

gtkmm 原来的名字是 gtk--,因为 GTK+ 的名字中已经含有一个 + 号。但是,对搜索引擎来说,索引 -- 符号不太容易,所以最后被定名为 gtkmm,这就是我们一直使用的原因。

为什么用 gtkmm 而不是 GTK+?

  • gtkmm 允许你写代码时使用常用的 C++ 的技术,比如,封装、派生和多态。作为一个 C++ 程序员,你可能已经意识到这会导致更清晰的,更好组织过的代码。
  • gtkmm 是更类型安全的,所以一些以前用 C 写的、只能在运行期检查出来的错误,现在可以在编译期被检查出来。这些特定的型别还使 API (应用程序接口) 更加清晰,因为仅从方法的声明就可以看出应当使用什么类型。
  • 可以使用继承技术来派生新的组件。在 GTK+ 中,用 C 代码来派生新的组件太复杂了,而且极易犯错,所以很少有 C 程序员这么做。作为一个 C++ 程序员,你知道,派生是一项重要的面向对象技术。
  • 可以使用成员变量,从而简化内存管理。所有的 GTK+ 的 C 组件都是用指针来处理的。作为一个 C++ 程序员,你知道,只要可能,就应当避免使用指针。
  • 更少的代码。GTK+ 的 C 对象模型使用带前缀的函数名称和类型转换宏。例如:

    gtk_button_set_text(GTK_BUTTON(button), "sometext");

    , 而 gtkmm 的 C++ 代码更短,而且更清晰。例如:

    button.set_text("sometext");
  • 不必担心 GTK+ 中不一致的引用记数策略。

为什么使用 libsigc++?就用通常的 GTK+ 信号处理函数不行么?

  • GTK+ 的信号不是类型安全的,所以编译器并不能告诉你,你的回调函数的参数的个数、类型或者返回值是否有错。
  • 它们只能作为全局函数或者静态方法来使用。使用 libsigc++,回调函数可以被设计为成员方法,可以使用特定物件的成员变量。它们还可以被设计为虚函数,你可以在派生类中再改写它们。

为什么 GTK+/GNOME 本身不用 C++ 写

  • C 是一种比较简单的语言,更多的人对之更熟悉一点,尤其是在 Unix 平台上。
  • C 可以被其它任何语言封装,使 API 可以为更多的开发者而用。
  • GTK+ 和 GNOME 的 C 代码被很好的组织过,比我们遇到过的大多数 C 代码都要清晰得多。这部分得益于基于 C 的面向对象的设计结构。

既然这么喜欢 C++,用Qt不就行了么?

gtkmm 的开发者们之所以选择 gtkmm 而不是 Qt,原因在于 gtkmm 按照更地道的 C++ 方式来做事。Qt 产生于 C++ 和(准)标准库还没有被标准化的时候,而且不能被编译器很好地支持。它与如今标准库中的许多东西都重复了,比如容器和类型信息。更重要的是,它修改 C++ 语言以实现信号功能,所以,Qt 类很难被其它非 Qt 类使用。而 gtkmm 不对 C++ 语言作任何修改,仍可以使用标准 C++ 来实现信号操作。

此外,gtkmm 和其它 *mm 模块允许你构建与 GNOME 桌面平台更紧密的软件。

gtkmm 有多好

它运行于什么操作系统下?

只要有合适的编译器和库,gtkmm 应该可以运行于任何类 UNIX 的系统上。GNU C++ (g++,gcc的一个组成部分)编译器和它的工具集(也可以在 Linux 和 *BSD 系统上找到它们)构成了它的缺省编译环境。

gtkmm 也可以由下列工具编译:

  • Sun 的 Forte C++,在 Solaris 平台上。
  • 在 Windows 平台上,可以用 mingw 工具编译,也可以用微软 Visual C++。

它有多完整?

gtkmm 试图提供 GTK+ 提供的所有功能。这意味您可以用 gtkmm 完成任何 GTK+ 所支持的事情,而且更加简单。如果还有什么部分没有覆盖到,希望能够通知我们。

gtkmm 支持 C++ 所有的优点么? 比如说继承,多态等等。

是的。gtkmm 对象对是普通的 C++ 对象,GTK+ 的继承也是通过 C++ 的继承实现的。对其它任何 C++ 对象可行的操作,对 gtkmm 组件同样可行。

gtkmm 使用标准 C++ (STL) 容器么? 比如说 std::string 和 std::list?

是的。只要可能,我们将坚定不移地重用标准 C++ 的代码。开始的时候,这可能并不太明显,因为:

  • gtkmm 使用 Glib::ustring,它和 std::string 有几乎相同的接口,因为 C++ 标准并不支持 UTF-8 编码的字符串。
  • gtkmm 使用类似 Glib::LIstHandle<int> 这样的接口,它可以被赋值给几乎所有的标准 C++ 容器,比如 std::list 或 std::vector。使用这些中间类型而不是强制你使用任何特定的容器。

另外,一些组件,比如 Gtk::TreeView,有一些和标准容器很类似的接口。举例来说,你可以在被选择的行中逐个迭代。

是否 gtkmm 都强制对 GTK+ 组件使用 STL 式的接口?

问:不论合适与否、麻烦与否或实现好不好,是否 gtkmm 都强制对 GTK+ 组件使用 STL 式的接口?

答:不,我们没有强迫你这样做。我们为一些容器组件提供了 STL 式的接口,以允许你在子组件中逐个迭代,但是除此以外还有更简单的接口。之所以这样做,是因为我们认为使用 STL 式的接口时,有时需要太多的代码去实现简单的工作。但从另一方面来说,有些人不论是否合适,虔诚地偏爱 STL 式的代码。所以,在这里你有选择的权利。

这些实现的 STL 接口使用类很简单的代码,而且工作起来没有任何问题。就如同你在 Bug 页面看到的那样,并没有关于它们的已知 Bug。

一些类,如 Gtk::TextBuffer 只有 STL 式的接口。这是因为下面的组件使用的就是 STL 式的接口,只不过是用C实现的。所以这是将这个 API 封装到 C++ 的最合适,也是最简单的办法。

gtkmm API 是否使用 C 类型,比如说结构体?

不。我们把所有的参数包装成了 C++ 的类,这些类使用 C++ 的内存管理。如果你发现还有没有特别原因的 C 类型的参数,希望能通知我们。

gtkmm 被用来写了些什么程序?

在 gtkmm 网站的 Additional Resources 页上,查看应用程序列表。

gtkmm 和 Qt 相比而言怎么样?

  • gtkmm 使用纯 C++。Qt 还需要扩展 C++,而这需要 moc 预处理器的进行解析。
  • gtkmm 使用 std::string、std::list、std::vector、iterators等等。Qt 有它自己特定的容器。
  • 使用 gtkmm 时,你可以使用 C++ 的内存管理方式。Qt 要求所有的组件作为指针来处理,并且组件的删除交由父组件来处理。
  • gtkmm 的组件的安排更加简单。在 Qt 中,容器和布局是分开的类,子组件必须被同时添加到它们两者中。
  • gtkmm 希望被设计出一个清晰的 API。Qt 类的经常依赖一些易混淆的重写过的构造函数的隐晦的功能。

你们是像对 GTK+ 那样,封装了所有的 GNOME API?

是的。我们在其它 *mm 模块中封装了大多数有用的并且稳定的 GNOME API。

gtkmm 很“臃肿”么?

不。gtkmm 是一个轻量级封装。

更多的信息

有 gtkmm 的邮件列表么?

是的。请看 订阅页面

关于 gtkmm,都有些什么文档?

有相当完整的教程、自动产生的API 参考文档,还有在gtkmm 文档页面上提供的大量的可以运行的例子。

我在哪里可以找到例子代码?

请看 gtkmm-documentation 模块下的 examples 目录。大部分都是 gtkmm 教程中提到的。那里还有一些比较大的第三方应用程序,你可以调试一下它们的代码。

使用 gtkmm

编译 gtkmm 程序时,我应当使用哪些编译器参数?

请看 gtkmm 教程中 《头文件和链接》。

如何从 gtkmm 对象得到一个 GTK+ 对象?

如果你需要一些 gtkmm 所不支持的 GTK+ 功能,你可以调用 <command>Gtk::Widget::gobj()</command> (在gtkmm 1.x 的版本中是<command>gtkobj()</command>) ,这将返回一个指向纯 C 的 GTK+ 数据结构的指针。你可以直接操作这个 C 对象,就像在任何 GTK+ 程序里做的那样。

=== 如何将 GTK+ 对象封装到一个 gtkmm 实例中?===

Glib::wrap() 会返回一个指向 gtkmm 对象的指针。这是一个重载函数,所以它会给你一个恰当类的实例。

=== 在 gtkmm 中可以使用 C++ 异常么?===

是的,可以,但这并不是一个好主意。官方的回答是这样,既然纯 C 不知道 C++ 的异常是什么,在你的函数调用栈里,只要抛出器和捕捉器之间没有 C 函数,你就可以在你的 gtkmm 代码里使用异常。这意味着你必须局部地捕捉自己抛出的异常。

对于运行期间没有被捕捉的异常,你会得到一个警告。并且对于未被捕捉的异常,你可以指定不同的处理句柄。一些 gtkmm 方法甚至使用异常来报告错误。在这些方法的参考文档里已经列出了这些将可能抛出的异常类型。

如何将 Glade 和/或 libglade 与 gtkmm 配合使用?

请看 gtkmm 教程中《Glade 与 Gtk::Builder》。

Gtk::manage(widet) 是做什么用的?

意思是“容器组件将负责删除这个组件。”一些人喜欢用它,因为他们再也不必为组件的删除而操心了。只有当你用 add() 方法添加一个组件到容器组件中的时候,才能使用 Gtk::manange()。

我应当如何学习安排组件? 我被包装参数搞晕了。

使用 Glade 来处理 GTK+ 和 GNOME 组件是一个很棒的方法。使用 Glade 去探究组件的选择,看看它们是如何被组合到一块儿的。然后,在你的构造函数里和 add()与pack() 方法里,可以使用相同的设置和相同的参数。或者你可以使用 Gtk::Builder (或libglademm) 在运行时加载 GUI 。

哪里有 Document 和 View?或者我如何使用 MVC 的设计模式?

问:我习惯使用 MFC。哪里有 Document 和 View?或者我如何使用 Document/View 的思想? 或者我如何使用 MVC 的设计模式?

答:

  • 尽管经常被 GTK+ 程序员们使用,但是 GTK+ 并不能直接支持 Document/View (MVC模式里一个非常有用的版本)。但是,TextViewTreeView的接口被分割为了 Model 和 View。

  • Bakery 库可以使 gtkmm/gnomemm 的 C++ 程序员们非常容易地使用 Document/View 框架。

使用 gtkmm 时,如何加载位图?

使用 Gdk::PixbufGtk::Image。两者都易于使用,并且通过 pixbuf 加载插件可以支持大量的图形文件类型。

gtkmm 是线程安全的么?

Paul Davis 写道:

不论是 X、GDK、GTK+ 或是 gtkmm,从它们本身来说,都是线程安全的。你要么使用 gdk_threads_{enter,leave}() 函数来保护所有的 GDK/GTK+/gtkmm 函数,要么你就得确定你只有一个线程在作这些调用。一个通常使用的作法是用一个非 GUI 线程通过管道向 GUI 线程发送请求 。这个管道使用钩子技术挂在 GTK 使用的 glib 的主消息循环上。

就个人来讲,我从来只用一个线程的那种作法,我发现它很适合我的程序。

注意,glibmm 带有 Glib::Dispatcher,它实现了上面提到的,使用管道技术进行线程间的信号处理。

Andress Rottmann 写道:

如果你需要一个线程间非常复杂的消息传递方法,看一下 libsigc++ extras。它在 libsigc++ 的基础上,提供了线程间的,类型安全的信号槽调用,和它一起的还有一个 gtkmm 例子

Chinese/gtkmm/FAQ (last edited 2010-05-01 18:29:05 by TaoWang)