《python核心编程》 第5章 GUI编程
本章将对图形用户界面(Graphical User Interface,GUI)编程进行简要的介绍。无论你刚接解本领域,还是希望学到更多相关知识,亦或是想要看到 Python 中是如何实现的,本章都会正合你意。这短短的一章不可能展示所有 GUI 应用开发的东西,但是会为你奠定一个坚实的基础。我们将主要使用的GUI 工具包是Python 默认的GUI 库Tk,通过Python 的接口Tkinter (“Tk interface”的缩写)可以访问 Tk。
Tk 并不是最新和最好的,也没有包含最强大的 GUI 构建模块集,但是它足够易用,你可以使用它构建能够运行在大多数平台下的 GUI。我们将给出几个使用 Tkinter 的简单和中等难度的例子,然后是几个使用其他工具包的例子。当你完成本章的学习后,你将有能力构建更为复杂的应用,并可以转而使用更加现代化的工具包。对于当前大多数主流的工具包(包括商业系统),Python 都有其对应的绑定或适配器。
- 5.1 简介
在开始GUI 编程之前,首先介绍Python 默认的 UI 工具包 Tkinter。我们将先从安装 Tkinter 开始,因为 Tkinter 不总是默认安装的(尤其是当你自己从源码构建 Python 的时候)。接下来会是一个对客户端/服务端架构的快速回顾,该话题在第 2 章中已经进行过介绍,不过在这里还会有一些关联。
5.1.1 Tcl、Tk 和 Tkinter
Tkinter 是Python 的默认GUI 库。它基于Tk 工具包,该工具包最初是为工具命令语言(Tool Command Language,Tcl)设计的。Tk 普及后,被移植到很多其他的脚本语言中,包括 Perl (Perl/Tk)、Ruby(Ruby/Tk)和 Python(Tkinter)。结合 Tk 的 GUI 开发的可移植性与灵活性,以及与系统语言功能集成的脚本语言的简洁性,可以让你快速开发和实现很多与商业软件品质相当的 GUI 应用。
如果你是 GUI 编程新手,会惊喜地发现它多么简单。此外,你还会发现使用 Python 和 Tkinter 可以提供给你一种高效而又令人兴奋的方法来创建有趣(可能还很有用)的应用,而如果直接使用 C/C++的原生窗体系统库进行编程则会花费较长的时间。一旦设计好了应用程序及其外观,就可以使用称为控件(widget)的基础构建块来拼凑出你想要的东西,最后再添加功能使其真实可用。
如果你是使用 Tk 的老手,无论熟悉的是 Tcl 还是 Perl,都会发现 Python 给予了 GUI 编程一种新的方式。最重要的是,它提供了一种更快速地构建 GUI 程序的原型系统。此外还要记住,你依然能够使用 Python 的系统访问、网络操作、XML、数值与可视化处理、数据库访问、所有其他标准库和第三方扩展模块。
只要系统中安装了 Tkinter,不超过 15 分钟时间就可以让你的第一个 GUI 程序运行起来。
5.1.2 安装和使用Tkinter
Tkinter 在系统中不是默认必须安装的,可以通过在 Python 解释器中尝试导入 Tkinter 模块(Python 1 和 2 版本,在 Python 3 中重命名为 tkinter)来检 查 Tkinter 是否可用。如果 Tkinter 可用,则不会有错误发生,如下所示。
>>> import Tkinter >>>
如果你的Python 解释器在编译时没有启用 Tkinter,模块导入将会失败。
>>> import Tkinter Traceback (innermost last): File “<stdin>”, line 1, in ? File “/usr/lib/pythonX.Y/lib-tk/Tkinter.py”, line 8, in ? import _tkinter # If this fails your Python may not be configured for Tk ImportError: No module named _tkinter
你可能需要重新编译 Python 解释器以使用Tkinter。这通常会涉及编辑 Modules/Setup 文件,然后启用所有正确的设置,来编译带有 Tkinter 的Python 解释器;或者勾选安装 Tk 到你的系统中。查阅 README 文件,以获取你的 Python 版本编译Tkinter 到系统中的特定说明。编译好解释器后,需要启动一个新的 Python 解释器,否则,它还会和没有 Tkinter(实际上, 它就是旧的解释器)的表现一样。
5.1.3 客户端/服务端架构
第 2 章介绍了客户端/服务端计算的概念。窗口系统是软件服务器的另一个例子,它们运行在一个带有显示设备(如显示器)的计算机中。同样地,还有需要客户端—需要在端窗口环境中执行的程序,也称为 GUI 应用。上述这些应用无法脱离窗口系统独立运行。
当引入网络编程后,该架构变得更加有趣。通常一个 GUI 应用执行时,它会在启动程序的计算机上进行显示(通过窗口服务器);但是在一些网络窗口环境中,也可以选择另一台计算机的窗口服务器进行应用的显示,例如UNIX 中的 X Window 系统。因此,可以在一台计算机上运行 GUI 程序,而在另一台机器上进行显示。
5.2 Tkinter 和 Python 编程
本节首先会介绍通用的 GUI 编程,然后会重点关注如何使用 Tkinter 及其组件创建 Python 的 GUI 程序。
5.2.1 Tkinter 模块:添加 Tk 到应用中
那么为了让 Tkinter 成为应用的一部分,你需要做些什么呢?首先,已经存在的应用并不是必需的。如果你愿意,可以创建一个纯 GUI 程序,不过没有让人感兴趣的底层功能的程序不会有什么用处。
让 GUI 程序启动和运行起来需要以下 5 个主要步骤。
1.导入 Tkinter 模块(或 from Tkinter import *)。
2.创建一个顶层窗口对象,用于容纳整个 GUI 应用。
3.在顶层窗口对象之上(或者“其中”)构建所有的 GUI 组件(及其功能)。
4.通过底层的应用代码将这些 GUI 组件连接起来。
5.进入主事件循环。
第一步是琐碎的:所有使用 Tkinter 的 GUI 程序都必须导入 Tkinter 模块。获得 Tkinter 的访问权是首要步骤(参见 5.1.2 节)。
5.2.2 GUI 编程介绍
在举例之前,先简单介绍 GUI 应用开发。这将为你今后的学习提供一些通用的背景知识。创建一个 GUI 应用就像艺术家作画一样。传统上,艺术家使用单一的画布开展创作。
其工作方式如下:首先会从一块干净的石板开始,这相当于用来构建其余组件的顶层窗口对象。可以将其想象为房屋的地基或艺术家的画架。换句话说,必须在浇灌好混凝土或搭建起画架之后,才能把真实的结构或画布拼装在上面。在 Tkinter 中,这个基础称为顶层窗口对象。
窗口和控件
在 GUI 编程中,顶层的根窗口对象包含组成 GUI 应用的所有小窗口对象。它们可能是文字标签、按钮、列表框等。这些独立的 GUI 组件称为控件。所以当我们说创建一个顶层窗口时,只是表示需要一个地方来摆放所有的控件。在Python 中,一般会写成如下语句。
top = Tkinter.Tk() # or just Tk() with “from Tkinter import *”
Tkinter.Tk()返回的对象通常称为根窗口,这也是一些应用使用 root 而不是 top 来指代它的原因。顶层窗口是那些在应用中独立显示的部分。GUI 程序中可以有多个顶层窗口,但是其中只能有一个是根窗口。可以选择先把控件全部设计好,再添加功能;也可以边设计控件边添加功能(这意味着上述步骤中的第 3 步和第 4 步会混合起来做)。
控件可以独立存在,也可以作为容器存在。如果一个控件包含其他控件,就可以将其认为是那些控件的父控件。相应地,如果一个控件被其他控件包含,则将其认为是那个控件的 子控件,而父控件就是下一个直接包围它的容器控件。
通常,控件有一些相关的行为,比如按下按钮、将文本写入文本框等。这些用户行为称为事件,而 GUI 对这类事件的响应称为回调。
事件驱动处理
事件可以包括按钮按下(及释放)、鼠标移动、敲击回车键等。一个 GUI 应用从开始到结束就是通过整套事件体系来驱动的。这种方式称为事件驱动处理。
最简单的鼠标移动就是一个带有回调的事件的例子。假设鼠标指针正停在 GUI 应用顶层窗口的某处。如果你将鼠标移动到应用的另一部分,鼠标移动的行为会被复制到屏幕的光标上,于是看起来像是根据你的手移动的。系统必须处理的这些鼠标移动事件可以绘制窗口上的指针移动。当释放鼠标时,不再有事件需要处理,此时屏幕会重新恢复闲置的状态。
事件驱动的 GUI 处理本质上非常适合于客户端/服务端架构。当启动一个 GUI 应用时, 需要一些启动步骤来准备核心部分的执行,就像网络服务器启动时必须先分配套接字并将其绑定到本地地址上一样。GUI 应用必须先创建所有的 GUI 组件,然后将它们绘制在屏幕上。这是布局管理器(geometry manager)的职责所在(稍后会详细介绍)。当布局管理器排列好所有控件(包括顶层窗口)后,GUI 应用进入其类似服务器的无限循环。这个循环会一直运行,直到出现 GUI 事件,进行处理,然后再等待更多的事件去处理。
布局管理器
Tk 有 3 种布局管理器来帮助控件集进行定位。最原始的一种称为 Placer。它的做法非常直接:你提供控件的大小和摆放位置,然后管理器就会将其摆放好。问题是你必须对所有控件进行这些操作,这样就会加重编程开发者的负担,因为这些操作本应该是自动完成的。
第二种布局管理器会是你主要使用的,它叫做 Packer,这个命名十分恰当,因为它会把控件填充到正确的位置(即指定的父控件中),然后对于之后的每个控件,会去寻找剩余的空间进行填充。这个处理很像是旅行时往行李箱中填充行李的过程。
第三种布局管理器是 Grid。你可以基于网格坐标,使用 Grid 来指定 GUI 控件的放置。
Grid 会在它们的网格位置上渲染 GUI 应用中的每个对象。本章将使用Packer。
一旦Packer 确定好所有控件的大小和对齐方式,它就会在屏幕上将其放置妥当。
当所有控件摆放好后,可以让应用进入前述的无限主循环中。在 Tkinter 中,代码如下所示。
Tkinter.mainloop()
一般这是程序运行的最后一段代码。当进入主循环后,GUI 就从这里开始接管程序的执 行。所有其他行为都会通过回调来处理,甚至包括退出应用。当选择File 菜单并单击Exit 菜单选项,或者直接关闭窗口时,就会调用一个回调函数来结束这个 GUI 应用。
5.2.3 顶层窗口:Tkinter.Tk()
之前提到过所有主要控件都是构建在顶层窗口对象之上的。该对象在 Tkinter 中使用 Tk
类进行创建,然后进行如下实例化:
>>> import Tkinter >>> top = Tkinter.Tk()
在这个窗口中,可以放置独立的控件,也可以将多个组件拼凑在一起来构成 GUI 程序。那么有哪些种类的控件呢?现在就介绍这些Tk 控件。
5.2.4 Tk 控件
在本书写作时,总共有 18 种 Tk 控件,表 5-1 所示为这些控件的描述。最新的控件有LabelFrame、PanedWindow 和 Spinbox,这些都是从 Python 2.3 版本开始增加的(通过 Tk 8.4)。
我们将不会对 Tk 控件进行详细介绍,因为已经有很多不错的文档可以供你参阅了,比如 Python 主站上的 Tkinter 主题页,或大量印刷资源和网上关于 Tcl/Tk 的资源(可以参见附录 B)。不过,后面会给出几个简单的例子来帮助你起步。
核心提示:默认参数是你的朋友 |
GUI 开发利用了Python 的默认参数,因为 Tkinter 的控件中有很多默认行为。除非你非常清楚自己所使用的每个控件的每个可用选项的用法,否则最好还是只关心你要设置的那些参数,而让系统去处理剩下的参数。这些默认值都是精心选择出来的。即使没有提供这些值,也不用担心应用程序在屏幕上的显示会有什么问题。作为一条基本规则,程序是由一系列优化后的默认参数创建的,只有当你知道如何精确定制你的控件时,才应该使用非默认值。 |