5.4.2 案例:图形库 graphics

如前所述,Tkinter 是 Python 语言的标准库,可以利用 Tkinter 中的画布构件来绘制图形。 虽然利用 Tkinter 来进行图形编程已经比较简单、方便,但对初学者来说可能还是有点小麻 烦。例如,画布甚至都没有提供画“点”的方法,初学者希望画点时往往不知怎么办。又如, 圆形一般都是通过圆心和半径来定义的,但在画布上画圆形时必须利用界限框(外接正方形) 来定义。另外,对图形的各种操作(如移动图形、修改图形的选项值等)都是通过调用画布 的方法来执行的,而根据面向对象的思想,更容易理解的做法应该是直接针对图形对象发出 操作请求。

由于上述理由,有人①在 Tkinter 之上写了一个更容易使用的图形库——graphics。这个 图形库是为教学目的而开发的,它将 Tkinter 的绘图功能以面向对象的方式重新包装了一下, 使得初学者更容易学习和应用。使用 graphics 提供的功能实际上就是使用 Tkinter 的功能, 但使用者并不知道这一点,也不需要知道这一点,这就是层次体系结构带来的效果。图 5.23 显示了 graphics 与 Tkinter 之间的关系,其中提到的 graphics 定义的各种图形类将在稍后介 绍。

① Python Programming: An Introduction to Computer Science 的作者 John Zelle。

图 5.23 在 Tkinter 之上开发的 graphics

graphics 模块和说明文档可以从下列网站下载:

http://mcsp.wartburg.edu/zelle/python

下载后将 graphics.py 模块与你的图形程序放在一个目录中,或者放在 Python 安装目录 中即可。下面我们简要介绍如何使用 graphics 模块。

首先,需要导入 graphics 模块:

>>> from graphics import *

其次,创建一个绘图窗口:

>>> win = GraphWin("My Graphics Window",300,200)

这条语句的含义是在屏幕上创建一个窗口对象,窗口标题为"My Graphics Window",宽 度为 300 像素,高度为 200 像素。三个参数都可以省略,缺省宽度和高度都是 200 像素。窗 口的坐标系仍然是我们熟悉的,即以窗口左上角为原点,x 轴向右,y 轴向下。

通过 Graphwin 类创建绘图窗口的界面实际上是对底层 Tkinter 中创建画布对象界面的重 新包装,也就是说,当程序员利用 graphics 模块创建绘图窗口时,系统会把这个请求向下转 达给 Tkinter 模块,而 Tkinter 模块就创建一个画布对象并返回给上层的 graphics 模块。这样 做不是没事找事多此一举,而是为了改善图形编程界面的易用性、易理解性。

接下去就可以在作图窗口中绘制图形了,稍后将介绍各种图形对象的创建方法。程序结 束后应该关闭图形窗口,为此只需向窗口对象发如下消息即可:

>>> win.close()

下面介绍 graphics 模块支持的各种图形对象的用法。演示代码中总是假定已经导入了 graphics 模块并创建了绘图窗口 win。

graphics 模块提供了类型 Point 用于在窗口中画点。创建点对象的语句模式为:

>>> p = Point(<x 坐标>,<y 坐标>)

下面通过一个交互过程来在窗口中创建 Point 对象,并演示 Point 对象的方法的使用。

>>> p = Point(100,80)
>>> p.draw(win)
>>> print p.getX(),p.getY() 100 80
>>> p.move(20,30)
>>> print p.getX(),p.getY() 120 110

第一条语句创建了一个 Point 对象,该点的坐标为(100,80),变量 p 被赋值为该对象。

这时在窗口中并没有显示这个点,因为还需要让这个点在窗口中画出来,为此只需向对象 p 发送消息 draw(),这就是第二条语句的目的,其意为“请求对象 p 执行 draw(win)方法, 即在窗口 win 中将自己画出来”。第三条语句演示了 Point 对象的另两个方法 getX()和 getY()的使用,分别是获得点的 x 坐标和 y 坐标。第四条语句的含义是请求 Point 对象 p 改变位置,向 x 方向移动 20 像素,向 y 方向移动 30 像素。

此外,Point 对象还提供以下方法:

  • p.setFill():设置点 p 的颜色。

  • p.setOutline:设置轮廓线的颜色。对 Point 来说,与 setFill 没有区别。

  • p.undraw():隐藏对象 p,即在窗口中变成不可见的。注意,隐藏并非删除,对象 p 仍然存在,随时可以重新执行 draw()。

  • p.clone():复制。复制一个与 p 一模一样的对象。

读者一定会觉得通过 Point 类来画点非常容易,但也会奇怪:graphics 是建立在 Tkinter 之上的一层软件,graphics 的所有功能都是依赖于 Tkinter 的功能实现的,但是 Tkinter 中并未提供画点功能啊。对这个疑问的解答很简单:Point 对象其实是 Tkinter 中的一个很小的矩 形(参见图 5.23)!这是通过层次化改善图形编程界面的一个典型例子——当我们要画点时, 就直接创建 Point 对象,而不是像在 Tkinter 中那样很别扭地创建一个矩形。

接下去介绍的其他图形对象就不再像 Point 这样详细解释并演示用法了,希望使用 graphics 模块的读者可以自行练习。

直线

直线类型为 Line,创建直线对象的语句模式为:

>>> line = Line(&lt;端点 1&gt;,&lt;端点 2&gt;)

其中两个端点都是 Point 对象。

和 Point 一样,Line 对象也支持 draw()、undraw()、move()、setFill()、setOutline()、clone()等方法。此外,Line 对象还支持 setArrow()方法,用于为直线画箭头。

圆形

圆形类型为 Circle,创建圆形对象的语句模式为:

>>> c = Circle(&lt;圆心&gt;,&lt;半径&gt;)

其中圆心是 Point 对象,半径是个数值。

Circle 对象同样支持 draw()、undraw()、move()、setFill()、setOutline()、clone()等方法。此外,Circle 对象还支持 c.getRadius()方法,用于获取圆形对象 c的半径。

椭圆

椭圆类型为 Oval,创建椭圆对象的语句模式为:

>>> o = Oval(&lt;左上角&gt;,&lt;右下角&gt;)

其中左上角和右下角是两个 Point 对象,用于指定一个矩形,再由这个矩形定义一个内接椭圆。

椭圆对象同样支持 draw()、undraw()、move()、setFill()、setOutline()、 clone()等方法。

矩形

矩形类型为 Rectangle,创建矩形对象的语句模式为:

>>> r = Rectangle(&lt;左上角&gt;,&lt;右下角&gt;)

其中左上角和右下角是两个 Point 对象,用于指定矩形。

矩形对象同样支持 draw()、undraw()、move()、setFill()、setOutline()、clone() 等方法。此外,矩形还支持的方法包括 r.getP1() 、 r.getP2() 和 r.getCenter(),分别用于获取左上角、右下角和中心,返回值都是 Point 对象。

多边形

多边形类型为 Polygon,创建多边形对象的语句模式为:

>>> poly = Polygon(&lt;顶点 1&gt;,..., &lt;顶点 n&gt;)

将各顶点用直线相连,即成多边形。

矩形对象同样支持 draw()、undraw()、move()、setFill()、setOutline()、 clone()等方法。此外还支持方法 poly.getPoints(),用于获取多边形的各个顶点。

文本

文本类型为 Text,创建文本对象的语句模式为:

>>> t = Text(&lt;中心点&gt;,&lt;字符串&gt;)

其中,中心点是个 Point 对象,字符串是显示的文本内容。

文本对象支持 draw()、undraw()、move()、setFill()、setOutline()、clone()等方法,其中 setFill()和 setOutline()方法都是设置文本的颜色。文本对象还支持方法 t.setText(<新字符串>)用于改变文本内容,方法 t.getText()用于获取文本内容,方法 t.setTextColor()用于设置文本颜色。