wxPython,一个 GUI 工具包
对于“现实世界”中的许多人来说,MS Windows 是一个不可避免的,尽管令人遗憾的事实。这些人中的一些人甚至可能有客户或老板,他们最终需要一个“标准”的 Windows GUI 应用程序。对于许多开发人员来说,能够选择最适合手头任务的工具,而不是被告知要使用哪个工具,是他们生活质量的一个基本要素,而 Linux 是一个令人愉快的开发环境。
事实上,现在可以在 Linux 上为 Windows 进行高质量、快速的 GUI 开发,并且对于其他 GUI 系统(如 Apple Macintosh、BeOS 或 OS/2)也越来越有可能。我在本文中介绍的工具之一是 wxPython,它不仅基于经过验证的工具包 wxWindows,而且使用了我们最喜欢的语言 Python。
Linux 下不乏 GUI 开发系统或工具包的选择,其中相当一部分可以称为可移植的,即可以在至少两个不同的平台上工作,例如 Linux/UNIX+X11 和 Windows。它们中的许多是免费的,但并非所有都处于可用形式(即,有文档记录、维护、相对无错误且功能丰富)。然而,我们很幸运,这些工具确实存在。事实上,一个维护良好的网页 http://www.free-soft.org/guitool/ 列出了令人印象深刻的工具包数量。问题是决定选择哪一个,因为生命太短暂,无法全部尝试。
生活是一系列的妥协。通常,问题是找出为了哪些好处,你准备接受哪些缺点。对于我的一个项目,我最终确定了以下列表
与 Linux、Windows 和 Python 兼容
可用
足够大的控件集
不太慢
紧凑
易于学习
如有必要,在原型设计阶段后易于转换为 C/C++
外观良好
在撰写本文时,wxPython 的版本为 2.1.13。它的作者 Robin Dunn 在封装 wxWindows 方面做得非常出色,wxWindows 是一个经典的 C++ GUI 工具包,已经存在多年。由于其相对悠久的历史和普及程度,wxWindows 已被移植到许多工具包和平台,并拥有相对较大的控件集合。对于 Linux,wxPython 使用的 wxWindows 版本是 wxGTK,即 wxWindows 到 GTK 的接口。对于 Windows,使用了 wxWindows 到 win32 的移植版本。
wxWindows 到 Python 的接口非常透明。概念相同,命名约定也基本相同。工具包的面向对象性质得到了保留。如果您知道如何使用 C++ 和 wxWindows 进行编程,那么您在使用 wxPython 时不会有任何问题。相反,如果您在 wxPython 中有一个可行的概念验证,那么将全部或部分移植到 C++ 以获得更好的速度应该是直接的。
wxPython 非常紧凑,但不包含在标准 Python 发行版中。请参阅“资源”部分,了解在哪里获取该软件。我发现 wxPython 很容易学习;该发行版附带了大量有用的演示,我将在示例中使用它们。
wxPython 的所有内容都是开源的,因此人们可以贡献代码并修复错误。总的来说,软件质量很高。
尽管 wxPython 具有所有优点,但它确实有一些小的缺点。在撰写本文时,wxWindows 的封装尚未完成,但 Robin Dunn 和其他人正在努力完成。
文档既非常完整又几乎不存在。Robin 可以这样做,因为 wxPython 与 wxWindows 非常相似,因此 wxWindows 文档(非常出色且完整)可以替代使用。Python 特定的文档被简化为文本中的少量注释(例如,如果某个功能不可用或略有不同)以及文档末尾的一小部分。将 C++ 类型调用转换为 Python 几乎不需要任何努力,但是如果您一生中从未见过 C++ 代码,这可能会非常令人反感。
该产品仍然处于积极开发中。它与 wxGTK 非常接近,但它所基于的 wxGTK 版本是一个不稳定的开发版本。这意味着许多东西可能无法完美运行,并且版本之间可能会发生很大变化。我在 Linux 下打印时遇到了很多问题,但在 Windows 下却完美运行。
wxPython 可能会从逐步教程中获益匪浅。在您阅读本文时,很可能已经有人写了一篇。
交互式 GUI 构建工具也会引起人们的兴趣。我了解到,很快就可以重用 wxWindows 中的工具。
如果您拥有 Debian 或基于 RPM 的系统,wxPython 的安装非常简单,因为 Robin Dunn 在他的网页 http://wxpython.org/ 上提供了这两种软件包。您需要安装 wxGTK(同样,也提供了软件包)以及 Mesa-3.0。
清单 1 显示了强制性的“hello world”应用程序。在第 14 行创建了一个固定大小的框架。在第 18 行,一个面板附加到框架,在面板内,在第 19-20 行创建了一个静态文本区域,以默认字体显示“Hello world of wxPython”。应用程序子类定义在第 23-32 行显示。创建、显示我们的框架的实例并将其置于前台。如果这些定义是独立运行的,而不是在另一个应用程序中导入的,则在第 36-37 行定义并运行应用程序类的实例。
请注意即使在这个非常简单的示例中也系统地使用了面向对象的框架。框架和应用程序是预定义类的子类。我们只需要重新定义我们用来使程序工作的方法。图 1 显示了这个令人印象深刻的应用程序的屏幕截图。

图 1. “Hello”应用程序的屏幕截图
有人可能会说,对于一个基本上什么都不做的简单应用程序来说,大约 40 行代码太多了。事实上,您可能会将其缩减到几行,但目标是呈现一个结构相对良好的代码片段,该代码片段易于构建。
有许多函数调用使用 -1 作为第二个参数,例如 panel = wxPanel(self, -1)。在这些情况下,值 -1 是正在创建的对象的强制性数字标识符,在将控件连接在一起时使用,我们将在第二个示例中看到。值 -1 表示“默认”,当此对象 ID 不会在代码中的任何位置使用时很有用。
在前面的示例中,控件在窗口中的位置是固定的,除了通过窗口管理器之外,我们无法控制应用程序:没有菜单,没有退出按钮等。此外,获取“hello world”消息有点无聊,所以这里有一个功能更多且更长的应用程序。应用程序如清单 2 所示。在第二个示例中,程序的结构基本相同:我们有一个子类化的 Frame 和一个子类化的 Application。Frame 子类重新定义了 __init__ 函数。在重新定义的 __init__ 中,我们在第 13-18 行定义了一些比“hello”更有趣的消息,在第 19 行定义了一个计数变量,在第 20-25 行定义了一个菜单表。和以前一样,我们在第 27 行调用父级的 __init__ 函数,在第 30 行创建一个面板,在第 31 行创建一些静态文本字段,并在第 34 行创建一个按钮。第 36-43 行专门用于窗口主要部分的布局。基本上,我们将静态文本放在固定位置;在它下面是一个按钮,位于窗口底部,无论窗口有多宽,该按钮都相对于窗口的左右部分保持居中。这是使用许多 wxBoxSizer 对象完成的。在第 45 行,我们将第 42 行定义的按钮和第 69 行定义的 OnButtonClick 方法之间关联一个按钮事件。按下按钮时将调用此方法。
在第 47 行,我们将应用程序关闭事件与第 76 行定义的 OnCloseWindow 方法关联起来。使用此方法,我们构建一个快速消息对话框,以询问用户是否确认。在第 48-64 行,我们创建一个状态行,菜单工具提示将在其中显示。应用程序的主菜单由 myMenuTable 中的规范定义,第 20-25 行。请注意,“New”菜单项也将调用第 81 行的方法。在菜单项的定义(第 24-29 行)中,字母前的字符 & 表示键盘快捷键(键入 ALT + 字母调用菜单项)。
在第 65-67 行,我们使窗口布局适合在一起,并将 wxBoxSizer 对象的自动调整大小功能设置为“on”。第 69-72 行定义了来自菜单项和按钮的回调方法。此方法只是重新定义了第 31 行定义的静态文本对象中的文本内容。多次按下按钮会连续显示 self.myFortunes(第 13-18 行)中定义的字符串。第 87-88 行的方法从“Exit”菜单项调用,并调用 Close 事件,该事件将关闭应用程序。第 90-106 行与“hello”示例相同。图 2 显示了此应用程序的屏幕截图。
这个“玩具”应用程序更有趣的点是如何实现窗口布局(使用 wxBoxSizer)以及如何连接事件和控件(在本例中使用 EVT_MENU 和 EVT_BUTTON)。事实上,就目前而言,只有按钮的布局令人满意;主文本仍然在固定位置——完整的解决方案太长,无法在此处展示。
请注意 self.something 变量的使用。如果要跨方法访问变量,则必须以这种方式调用它(self 是对象实例)。如果变量是方法私有的,则不需要 self 前缀。
如上所述,wxPython 的完整教程尚未准备就绪,尽管正在编写中。wxPython 支持的几乎所有控件都在发行版附带的演示应用程序中进行了演示。由于示例简洁明了,因此可以很快地从中学到东西。
目前,我们正在享受越来越多的可用工具包,我感觉 wxPython 是其中较好的工具包之一。与大多数用 Python 编写的东西一样,wxPython 中的程序往往紧凑、易于阅读和维护且功能强大。可用控件的范围与 MFC(Microsoft 基础类)不匹配,但对于大多数应用程序来说已经足够了。我个人认为,这个特殊的工具包最终使 RAD(快速应用程序开发)概念可用于 Linux。用此框架编写的应用程序也可以在 Windows 上运行,这对某些人来说将是一个巨大的好处。
就目前而言,wxPython 可能还无法取代 Tkinter 作为默认的 Python GUI 工具,至少在 wxWindows 的 Apple Macintosh 端口完成并发布稳定版本之前。但它显示出很大的希望,因为它是一个更高级别的工具包。

Hugues Talbot (hugues.talbot@cmis.csiro.au) 是一位居住在澳大利亚的法国人。因此,他喜欢吃喝、烹饪和惹恼他的同事。他的妻子不断提醒他找一个与计算机无关的爱好。