最初,GTK+ 是作为另一个著名的开放源码项目 —— GNU Image Manipulation Program (GIMP) —— 的副产品而创建的。在开发早期的 GIMP 版本时,Peter Mattis 和 Spencer Kimball 创建了 GTK(它代表 GIMP Toolkit),作为 Motif 工具包的替代,后者在那个时候不是免费的。(当这个工具包获得了面向对象特性和可扩展性之后,才在名称后面加上了一个加号。)
这差不多已经 10 年过去了。今天,在 GTK+ 的最新版本 —— 2.8 版上,仍然在进行许多活动,同时,GIMP 无疑仍然是使用 GTK+ 的最著名的程序之一,不过现在它已经不是惟一的使用 GTK+ 的程序了。已经为 GTK+ 编写了成百上千的应用程序,而且至少有两个主要的桌面环境(Xfce 和 GNOME)用 GTK+ 为用户提供完整的工作环境。
为什么使用 GUI 工具包?
使用 GTK+ 这样的库比起编写自己的 GUI 代码来有多个优势。例如,它可以显著节约开发时间,让开发人员把精力集中在项目真正重要和真正独特的地方,而不必重复公共的功能。对于用户来说,这意味着他们使用的应用程序之间具有更好的一致性:工具包能在哪使用,应用程序就能跟到哪里。就像使用 LEGO 一样,所有的人都使用同一兼容尺寸这一事实,意味着设计可以在使用库的人之间共享,不论他们在哪里使用它。
在现实中,现代的 GUI 工具包做的工作不仅仅是避免重复。它们提供了许多高级功能,用户希望在他们的应用程序中拥有这些功能,但是用别的方法得不到这些功能,因为在这类工具包上所投入的时间和工作,要远远超过在单一应用程序上的花费。所以,如果在应用程序中使用 GUI 对您来说很重要,那么请使用工具包。除此之外别无他法。现在剩下的惟一问题就是,应当使用哪个工具包?
GTK+ 的优势
不论开发的需要是什么,GTK+ 可能就是您正在寻找的答案。GTK+ 提供了许多东西:
它既现代,而且得到了积极的开发与维护,围绕它有一个充满活力的社区。
它提供了广泛的选项,用于把工作扩展到尽可能多的人,其中包括一个针对国际化、本地化和可访问性的完善的框架。
它简单易用,对开发人员和用户来说都是这样。
它的设计良好、灵活而可扩展。
它是自由软件,有一个自由的开放源码许可。
它是可移植的,从用户和开发人员的角度都是这样。
现代的且开发积极的工具包
GTK+ 是采用软件开发中的最新技术开发的,只要发现缺陷(肯定有缺陷,因为没有任何软件是完美的),开发人员就会尽力在下一版本中修补缺陷。使用现代的软件意味着,您不会陷在过时的工作中,而跟不上时代的发展。
持续的维护和开发也意味着您拥有影响工具包的未来发展方向的能力。另外,在出现新的发行版时,会引入基于用户反馈的新特性和新功能,而旧的问题则得到修补。
国际化、本地化和可访问性
在创建要让所有人使用的软件的时候,请记住三个关键字:国际化、本地化和可访问性(通常分别缩写为 i18n、l10n 和 a11y)。
国际化 是将程序准备为被母语不是开发应用程序所采用的语言的人使用的过程,所以应用程序不依赖于对任何特定语言的任何假设。
i18n 远远不只是对程序使用的文本进行翻译。它还意味着要考虑所使用的不同脚本和字母表、不同的编写方向、显示许多语言所需要的特殊处理以及为用户提供输入文本的适当方法。不是每种语言都可以简单地把每个字母映射到键盘上的不同键,而且还必须实现更好的复杂性,例如确保在错误消息中使用正确的复数。
本地化 与 i18n 密切相关,因为为国际用户准备应用程序不仅仅是改变语言。程序还必须能够理解并尊重日期、货币显示、数字标注、文本排序所使用的不同习惯,以及许多可能不太注意的细节之处 —— 例如有些符号的使用,在世界的不同地方可能会被认为是不恰当的或无礼的。
正像 i18n,正确的 l10n 要求在代码中添加很多东西,而这些是事后很难轻松加入的。GTK+ 提供了针对 i18n 和 l10n 的恰当工具,会让代码(和二进制)可以在许多语言和地域上不加修改地运行。切换地域所需要的就是随操作系统(针对 l10n)或者一个可独立于实际的程序进行处理和发布的翻译文件(针对 i18n)一起发布的一组数据。带来的灵活性会得到开发人员、翻译者和用户的热爱。
可访问性 是让每个人都可以使用您的程序。有些用户的视力不佳,有些人可能不能用键盘或鼠标,而有些人可能只能移动他们的眼睛。要确保每个想使用您的应用程序的用户都能使用,需要做许多工作。幸运的是,GTK+ 提供了一个途径,可以通过一个完善的预先存在的 a11y 框架,立即得到这方面的支持,而您这边几乎什么工作也不需要做。使用这个框架(它是 UNIX® 系统上的事实标准),可以把应用程序带给各类用户。
您也能享受 a11y 的许多优势 —— 例如执行自动 GUI 测试的能力。通过让特殊需求用户运行的可访问性软件可以使用您的应用程序,您也可以让测试软件可以访问它,例如,检查行为是否正确 —— 这在传统的 GUI 编程中会带来严重的问题。(还值得记住的是:现在,a11y 不再被当作 “好” 东西。许多法规 —— 例如有关美国政府用软件的规则 —— 实际上要求软件对特殊需求的用户有恰当的支持。)
以上三点可能是使用工具包的充足理由 —— 特别是 GTK+,它在这三个领域都有优秀的支持。这个支持绝不完美,但在同类软件中是最好的,而且把这些关键字整合进应用程序的重要性并没有提到应有高度。在今天的世界中,计算机无处不在,用户众多而且独特,所以不能认为一个遗漏一整群用户的应用程序是一个完整的产品。
简单易用
这一点应当很明显,但是它实际上含义丰富。工具包对用户应当容易,这样才有可能创建简单的、直觉的和乐于使用的界面,哪怕针对的是新手。创建人机交互的正确模型不是一项简单的任务,GTK+ 正是长时间工作的结果,而且是众多的甚至困难的决策的结果。
GTK+ 对于开发人员也易于使用。它允许开发人员用简单的方式说出自己想要的东西,不会用所谓正规方式给开发人员带来负担,这些正规方式是计算机为了弥补它们固有的缺乏想像力的缺陷而施加给人类的负担。
设计良好、灵活和可扩展
编写 GTK+ 的方式允许在不扭曲基本设计的情况下,让维护人员添加新功能、让用户利用新功能。工具包也是可扩展的,这意味着可以向其中添加自己的块,并用使用内置块一样的方式使用它们。例如,可以编写自己的控制元素,比如说用于显示应用程序处理的科学数据,并让它正确地遵照用户选择的显示风格,就像 GTK+ 自身的控件那样。
更进一步,GTK+ 是可定制的,这样就可以让它适应自己的需求。GTK+ 有一个系统,可以在所有应用程序之间复制设置,包括主题的选择。主题 是一组一同发布的定制设置,会影响 GTK+ 使用的基本控件看起来的效果,甚至某种程度上的行为方式。使用主题,可以(例如)模拟另一个操作系统的观感。
带有自由开放源码许可的自由软件
自由软件 意味着每个人不仅可以自由地获得和使用这个工具包,还可以在满足某些条件的情况下修改并重新发布它。自由开放源码许可 意味着这些条件不是严格限制的,可以得到的自由程度是显著的。最重要的是,GTK+ 采用了 Lesser General Public License (LGPL) 许可,这是 GNU 许可家族中一个不太严格的许可。LGPL 允许自由地获取、修改和发布它覆盖的任何软件,只要对修改也保持自由即可。LGPL 还允许任何人使用该库提供的功能,而不 要求用户公开应用程序代码。(这对于许多工业应用来说很重要,因为由于以前的协议或许可,这种场合下一般不希望公开代码或者公开代码是显然不现实的。)使用 LGPL 许可,您既可以是开放源码社区的好伙伴也可以是好公民。
可移植
最后(但并不是最不重要),GTK+ 是可移植的。这意味着用户可以在许多平台和系统上运行它。另一方面,开发人员可以把软件提供给众多用户,却只要编写一次程序,还可以使用许多不同的编程和开发平台、工具和编程语言。所有这些都可以理解为更多的潜在用户,您可以利用更好地满足需求的更广泛的技能和工具。
所有这些优势组合在一起,让 GTK+ 成为软件开发的坚实基础。有了它,就能够把注意力集中在解决实际问题上,而不必重新发明轮子,而且您也可以确信创建的应用程序会按照用户预期的方式运作、解决他们的问题,而不必创建新的应用程序。
GTK+与MFC不完全对比
MFC已经江河日下,日渐式微,而GTK+可谓欣欣向荣,如日中天。这里无意于落井下石,痛打落水狗,贬MFC而尊GTK+。自己即在使用MFC也在使用GTK+,不会偏袒其中之任何一方。这个对比完全出于个人对两者的理解,说它是不完全对比,一方面只是一时兴起想做个笔记而已,另外一方面我对两者的理解也是有限的。
1. 两者都是基于面向对象设计的。尽管MFC是用C++写的,而GTK+是用C写的,但思想都是面向对象的。GTK+使用glib的对象机制,由于用C写的,其实现相对有点繁琐。
2. 两者都是基于消息驱动的。这是GUI系统的共性,消息可以是硬件上报的,如鼠标事件、键盘事件和触摸屏等等,也可以是程序产生,如一个窗口给另外一个窗口发送了一个消息。但两者并不完全相同,GTK+通过select挂在多个文件描述符上,可以同时等待多个事件源,比如socket、子进程退出和内核事件等等,而MFC只能通过GetMessage挂到消息队列上。
3. 两者都不是线程安全的,即只有一个线程可以操作GUI资源。主要是出于性能的考虑,这个问题不大,因大多数应用程序都是单线程的。而且它们都提供一些机制,让其它线程可以在必要时操作GUI资源。在GTK+中可以通过idle函数来实现,在MFC中可以通过PostMessage来实现(附带说明一下:Win32原生的GUI API是线程安全的)。
4. GTK+整合了一系列的基础函数库,功能强大,而MFC孤军做战,势单力薄。Glib是GTK+的基本库,里面实现了常见的容器和算法,可谓应有尽有,同时隔离了平台相关的功能。Pango是GTK+用于文字渲染的函数库,它负责控制不同文字的layout布局,而把字模的绘制交给freetype等字体函数库处理。MFC虽然实现了一些容器,但数量不多也不好用,除了对原生GUI API的包装外,没提供多少其它功能,与Microsoft Foundation Class Library这个名称一点都不相称。
5. GTK+是跨平台的,而MFC则不是。GTK+在设计时就考虑了可移植性,它按分层模型来组织整个系统,Glib封装了依赖于OS平台的函数,提供一套抽象的接口,在不同的平台有不同的实现。GDK封装了依赖于输入/输出设备的功能,如键盘事件的获取和显示缓冲的输出,同时实现了基本的绘图功能。GTK+几乎可以在所有PC平台下运行,而MFC从来都没有考虑过可移植性,它是与Win32 GUI绑定在一起的。
6. GTK+小巧,而MFC笨重。GTK+编译出来的可执行文件约3M左右,而MFC本身虽然不大,但它各种版本加在一起就可观了。MFC有ansi版本、有unicode版、有debug版、有release版、还有一些组合,如果你因此而晕倒了,那是很正常的。
7. GTK+的使用简单,MFC的使用繁琐。GTK+的使用比较简单,即使在没有工具的帮助下,要写一个GTK+的应用程序也不难,实际上绝大多数GTK+应用程序都是一行代码一行代码的敲出来的。而MFC的使用则太麻烦了,很难想象没有VC的向导的帮助,写一个基于MFC的应用程序。即有了VC的向导,仍有大量的程序员说MFC很难用。
8. GTK+使用signal机制,解开消息源与消息目标之间耦合。而MFC使用消息,将消息源与消息目标硬编码在一起。Signal的好处是,不需要知道目标是谁,谁关心谁就注册,这种出版订阅机制是解耦的最佳方式。而MFC的消息则是必须知道目标是谁,把消息源与消息目标死死的绑在一起。MFC提供了一套文档/视图框架,实现了类似出版订阅的功能,这本是设计者引以自豪的东西,结果因为太复杂不能被人理解,反而为开发人员所诟病。
9. GTK+采用layout机制动态计算各子窗口的坐标位置,自适应屏幕大小的变化。而MFC要求子窗口的坐标位置硬编码,结果要适应不同分辨率的屏幕非常困难。GTK+在窗口布局时分为两个阶段,第一个阶段父窗口先询问子窗口的最佳大小,第二个阶段父窗口根据自己的大小计算子窗口的实际大小,子窗口根据实际大小进行调整。
10. GTK+采用容器机制来合理分离控件的职责,MFC没有容器这个概念,很难实现递归组合。GTK+中差不多所有控件都是容器,都可以容纳其它任何控件,而MFC只有顶层窗口才是容器,可以容纳其它子控件。容器这个概念对代码重用的影响非常之大,这里举两个例子:其一是带图片的按钮(BitmapButton),在GTK+中它就是GtkImage和GtkLabel的组合,而在MFC中,图片和文字都要自己绘制。前者的GtkImage和GtkLabel可以在很多地方重用,而后都的绘制代码和事件处理代码只有自己才能使用。其二是列表框,在GTK+中,它只是一个容器,你可以向里面放编辑器、下拉框和其它任何者你想得到的控件。而在MFC中,即使只是实现一个不同外观的列表框,你都要采用自绘的方式,代码重用非常困难,向列表框中加入其它控件就更麻烦了,要使用一些非同寻常的手段不可。
11. GTK+采用容器机制优先使用组合而不是继承,符合现代设计的原则。MFC强制使用继承,使用麻烦而且耦合紧密。GTK+应用程序不需要继承任何窗口。MFC应用程序必须继承对话框或者其它顶层窗口才行,虽然可以采用中介者模式,把控件之间的交互集中在顶层窗口中,不需要继承控件,但仍然很麻烦。