### 5.2.2 创建画布
为了绘图,首先要有画布。Tkinter 中提供了画布(Canvas),可以在画布上绘制图形、 文本,也可以在上面放置命令按钮等 GUI 构件。画布实际上是一个 Canvas 对象,它包含 一些属性(如画布的高度、宽度、背景色等),也包含一些方法(如在画布上创建图形、删 除或移动图形等)。
创建画布对象的语句模板如下:
```
c = Canvas(<窗口>,<选项 1>=<值 1>,<选项 2>=<值 2>,...)
```
其中 Canvas 是 Tkinter 提供的类(class),所谓“类”其实就和 int、float 等一样是数据类型,只不过不是 Python 语言的内建类型,而是 Tkinter 模块带来的扩展类型。Canvas就像一个制造画布的工厂,每次执行 Canvas()都能制造出一个画布对象。参数<窗口>表示画布所在的窗口,诸<选项>=<值>为画布对象的选项(即属性)进行赋值。总之,整条语句创建一个 Canvas 对象,对该对象的数据进行设置,并将该对象赋值给变量 c(更准确的 说法是变量 c 引用该对象)。
画布的常用选项包括 height(画布高度)、width(画布宽度)和 bg(或 background, 画布背景色)等,需要在创建画布对象时进行设置。创建画布对象时如果不设置这些选项的 值,则各选项取各自的缺省值,例如 bg 的缺省值为浅灰色。画布对象的所有选项都可以在 创建以后的任何时候重新设置。
下面的语句在根窗口 root 中创建一个宽度为 300 像素①、高度为 200 像素、背景为白 色的画布:
```
>>> c = Canvas(root,width=300,height=200,bg='white')
```
注意,虽然至此已经创建了画布对象,但在根窗口中并没有看到这块白色画布,这就好 比从商店买来了画布,但还没有铺到桌子上一样。为了让画布在窗口中显现出来,还需要执 行如下“布置画布”的语句②:
```
>>> c.pack()
```
现在,我们在屏幕上看到原来的根窗口(背景色为浅灰色)中放进了一个 300x200 的白色画 布。如图 5.3 所示。
![](https://box.kancloud.cn/2016-02-22_56cafce058543.png)
图 5.3 放入画布后的根窗口
这里需要对 c.pack()所用到的“点表示法”加以说明。过去,当我们编写了一个函数f()来操作数据 x,传统的表示法是 f(x)。而在面向对象编程中,数据和操作被结合在一 起形成了对象,如果要对对象中的数据执行操作,通常采用点表示法——“对象.操作”。在 c.pack()中,变量 c 表示一个 Canvas 对象,pack()是 Canvas 对象能够响应的一个方 法,故 c.pack()就表示向对象 c 发出执行 pack()方法的请求。
> ① 像素(pixel)是能显示的最小图像单元,通俗说就是一个点。数字图像是由很多点组成的。
> ② 在窗口中布置各种构件需要使用布局管理器,这里的 pack()就是一种布局管理器。详见第 8 章。
坐标系
创建了画布,接下来就可以在画布上绘制各种图形了。为了在绘图时指定图形的绘制位 置,Tkinter 为画布建立了坐标系统。画布坐标系以画布左上角为原点,从原点水平向右为 x 轴,从原点垂直向下为 y 轴(图 5.4)。
![](https://box.kancloud.cn/2016-02-22_56cafce069362.png)
图 5.4 画布的坐标系统
坐标如果以整数给出,则度量单位是像素,例如左上角原点的坐标为(0,0),300x200的画布的右下角坐标为(299,199)。像素是最基本、最常用的长度单位,但 Tkinter 也支持以字符串形式给出其他度量单位的长度值,例如"5c"(5 厘米)、"50m"(50 毫米)、"2i"(2 英寸)等。
图形项的标识
一个画布上可能创建多个图形项①,因此需要有办法来标识、引用其中某个图形项,以 便对该图形项进行处理。画布上的图形项有两种标识方式:
+ 标识号:创建图形项时 Tkinter 自动为图形项赋予一个唯一的整数编号。
+ 标签:图形项可以与字符串型的标签(tag)相关联,每个图形项可以与 0、1 乃至 多个标签相关联,而同一个标签可以与多个图形项相关联。
标签相当于为图形项命名,只不过一个图形项可以有多个名字,而且不同图形项可以有 相同的名字。为图形项指定标签的方法有三种:一是在创建图形时利用选项 tags 来指定, 可以为 tags 选项提供单个字符串(单个名字),也可以提供一个字符串元组(多个名字); 二是在图形创建之后,任何时候都可以利用画布的 itemconfig()方法来设置;三是利用 画布的 addtag_withtag()方法来为图形项增添新标签。假设我们已经创建了画布 c,则 可以执行:
```
>>> r1 = c.create_rectangle(20,20,100,80,tags="#1")
>>> r2 = c.create_rectangle(40,50,200,180,tags=("myRect","#2"))
>>> c.itemconfig(r1,tags=("myRect","rectOne"))
>>> c.addtag_withtag("ourRect","rectOne")
```
> ① 每个图形项可以理解成一个图形对象(有自己的属性和操作),不过 Tkinter 没有采用为每种图形提供单 独的类来创建图形对象的实现方式。5.4.2 中介绍的 graphics 库则采用了更符合面向对象概念的实现。
其中第一行的含义是在画布 c 上创建了一个矩形(稍后详述),create_rectangle()返 回的标识号被赋值给变量 r1,同时将该矩形与标签"#1"相关联。同样地,第二行创建了另 一个矩形,该矩形的标识号被赋值给变量 r2,该矩形还与两个标签"myRect"和"#2"相关 联。第三行的含义是将第一个矩形的标签重新设置为"myRect"和"rectOne"(注意原标签"#1"即告失效),这里使用了标识号 r1 来引用第一个矩形。第四行的含义是为具有标签 "rectOne"的图形项(即第一个矩形)添加一个新标签"ourRect",这里使用了标签来引 用第一个矩形。至此,第一个矩形与 3 个标签"myRect"、"rectOne"和"ourRect"相关 联,其中任何一个都可用于引用该图形。注意,标签"myRect"同时引用两个矩形。
Canvas 还预定义了 ALL(或"all")标签,此标签与画布上的所有图形项相关联。
画布对象的方法
上面例子中介绍了画布对象的 itemconfig()和 addtag_withtag()方法,除此之 外,画布对象还提供很多方法用于对画布上的图形项进行各种各样的操作。将图形项的标识 号或标签作为参数传递给画布对象的方法,即可指定被操作的图形项。下面再介绍几个画布 对象的常用方法。
gettags()方法可用于获取与给定图形项相关联的所有标签。例如下面的语句显示标 识号为 r1 的图形项的所有关联标签:
```
>>> print c.gettags(r1) ('myRect', 'rectOne', 'ourRect')
```
find_withtag()方法可用于获取与给定标签相关联的所有图形项。例如下面的语句显示与"myRect"标签相关联的所有图形项,返回结果为各图形项的标识号所构成的元组:
```
>>> print c.find_withtag("myRect") (1,2)
```
delete()方法用于从画布上删除指定的图形项。例如下面的语句从画布上删除第一个矩形:
```
>>> c.delete(r1)
```
move()方法用于在画布上移动指定图形。例如,为了将第二个矩形在 x 方向移动 10像素,在 y 方向移动 20 像素,可以执行下列语句:
```
>>> c.move(r2,10,20)
```
读者可查阅 Tkinter 资料以了解更多的画布对象方法。
- 前言
- 第 1 章 计算与计算思维
- 1.1 什么是计算?
- 1.1.1 计算机与计算
- 1.1.2 计算机语言
- 1.1.3 算法
- 1.1.4 实现
- 1.2 什么是计算思维?
- 1.2.1 计算思维的基本原则
- 1.2.2 计算思维的具体例子
- 1.2.3 日常生活中的计算思维
- 1.2.4 计算思维对其他学科的影响
- 1.3 初识 Python
- 1.3.1 Python 简介
- 1.3.2 第一个程序
- 1.3.3 程序的执行方式
- 1.3.4 Python 语言的基本成分
- 1.4 程序排错
- 1.5 练习
- 第 2 章 用数据表示现实世界
- 2.1 数据和数据类型
- 2.1.1 数据是对现实的抽象
- 2.1.1 常量与变量
- 2.1.2 数据类型
- 2.1.3 Python 的动态类型*
- 2.2 数值类型
- 2.2.1 整数类型 int
- 2.2.2 长整数类型 long
- 2.2.3 浮点数类型 float
- 2.2.4 数学库模块 math
- 2.2.5 复数类型 complex*
- 2.3 字符串类型 str
- 2.3.1 字符串类型的字面值形式
- 2.3.2 字符串类型的操作
- 2.3.3 字符的机内表示
- 2.3.4 字符串类型与其他类型的转换
- 2.3.5 字符串库 string
- 2.4 布尔类型 bool
- 2.4.1 关系运算
- 2.4.2 逻辑运算
- 2.4.3 布尔代数运算定律*
- 2.4.4 Python 中真假的表示与计算*
- 2.5 列表和元组类型
- 2.5.1 列表类型 list
- 2.5.2 元组类型 tuple
- 2.6 数据的输入和输出
- 2.6.1 数据的输入
- 2.6.2 数据的输出
- 2.6.3 格式化输出
- 2.7 编程案例:查找问题
- 2.8 练习
- 第 3 章 数据处理的流程控制
- 3.1 顺序控制结构
- 3.2 分支控制结构
- 3.2.1 单分支结构
- 3.2.2 两路分支结构
- 3.2.3 多路分支结构
- 3.3 异常处理
- 3.3.1 传统的错误检测方法
- 3.3.2 传统错误检测方法的缺点
- 3.3.3 异常处理机制
- 3.4 循环控制结构
- 3.4.1 for 循环
- 3.4.2 while 循环
- 3.4.3 循环的非正常中断
- 3.4.4 嵌套循环
- 3.5 结构化程序设计
- 3.5.1 程序开发过程
- 3.5.2 结构化程序设计的基本内容
- 3.6 编程案例:如何求 n 个数据的最大值?
- 3.6.1 几种解题策略
- 3.6.2 经验总结
- 3.7 Python 布尔表达式用作控制结构*
- 3.8 练习
- 第 4 章 模块化编程
- 4.1 模块化编程基本概念
- 4.1.1 模块化设计概述
- 4.1.2 模块化编程
- 4.1.3 编程语言对模块化编程的支持
- 4.2 Python 语言中的函数
- 4.2.1 用函数减少重复代码 首先看一个简单的用字符画一棵树的程序:
- 4.2.2 用函数改善程序结构
- 4.2.3 用函数增强程序的通用性
- 4.2.4 小结:函数的定义与调用
- 4.2.5 变量的作用域
- 4.2.6 函数的返回值
- 4.3 自顶向下设计
- 4.3.1 顶层设计
- 4.3.2 第二层设计
- 4.3.3 第三层设计
- 4.3.4 第四层设计
- 4.3.5 自底向上实现与单元测试
- 4.3.6 开发过程小结
- 4.4 Python 模块*
- 4.4.1 模块的创建和使用
- 4.4.2 Python 程序架构
- 4.4.3 标准库模块
- 4.4.4 模块的有条件执行
- 4.5 练习
- 第 5 章 图形编程
- 5.1 概述
- 5.1.1 计算可视化
- 5.1.2 图形是复杂数据
- 5.1.3 用对象表示复杂数据
- 5.2 Tkinter 图形编程
- 5.2.1 导入模块及创建根窗口
- 5.2.2 创建画布
- 5.2.3 在画布上绘图
- 5.2.4 图形的事件处理
- 5.3 编程案例
- 5.3.1 统计图表
- 5.3.2 计算机动画
- 5.4 软件的层次化设计:一个案例
- 5.4.1 层次化体系结构
- 5.4.2 案例:图形库 graphics
- 5.4.3 graphics 与面向对象
- 5.5 练习
- 第 6 章 大量数据的表示和处理
- 6.1 概述
- 6.2 有序的数据集合体
- 6.2.1 字符串
- 6.2.2 列表
- 6.2.3 元组
- 6.3 无序的数据集合体
- 6.3.1 集合
- 6.3.2 字典
- 6.4 文件
- 6.4.1 文件的基本概念
- 6.4.2 文件操作
- 6.4.3 编程案例:文本文件分析
- 6.4.4 缓冲
- 6.4.5 二进制文件与随机存取*
- 6.5 几种高级数据结构*
- 6.5.1 链表
- 6.5.2 堆栈
- 6.5.3 队列
- 6.6 练习
- 第 7 章 面向对象思想与编程
- 7.1 数据与操作:两种观点
- 7.1.1 面向过程观点
- 7.1.2 面向对象观点
- 7.1.3 类是类型概念的发展
- 7.2 面向对象编程
- 7.2.1 类的定义
- 7.2.2 对象的创建
- 7.2.3 对象方法的调用
- 7.2.4 编程实例:模拟炮弹飞行
- 7.2.5 类与模块化
- 7.2.6 对象的集合体
- 7.3 超类与子类*
- 7.3.1 继承
- 7.3.2 覆写
- 7.3.3 多态性
- 7.4 面向对象设计*
- 7.5 练习
- 第 8 章 图形用户界面
- 8.1 图形用户界面概述
- 8.1.1 程序的用户界面
- 8.1.2 图形界面的组成
- 8.1.3 事件驱动
- 8.2 GUI 编程
- 8.2.1 UI 编程概述
- 8.2.2 初识 Tkinter
- 8.2.3 常见 GUI 构件的用法
- 8.2.4 布局
- 8.2.5 对话框*
- 8.3 Tkinter 事件驱动编程
- 8.3.1 事件和事件对象
- 8.3.2 事件处理
- 8.4 模型-视图设计方法
- 8.4.1 将 GUI 应用程序封装成对象
- 8.4.2 模型与视图
- 8.4.3 编程案例:汇率换算器
- 8.5 练习
- 第 9 章 模拟与并发
- 9.1 模拟
- 9.1.1 计算机建模
- 9.1.2 随机问题的建模与模拟
- 9.1.3 编程案例:乒乓球比赛模拟
- 9.2 原型法
- 9.3 并行计算*
- 9.3.1 串行、并发与并行
- 9.3.2 进程与线程
- 9.3.3 多线程编程的应用
- 9.3.4 Python 多线程编程
- 9.3.5 小结
- 9.4 练习
- 第 10 章 算法设计和分析
- 10.1 枚举法
- 10.2 递归
- 10.3 分治法
- 10.4 贪心法
- 10.5 算法分析
- 10.5.1 算法复杂度
- 10.5.2 算法分析实例
- 10.6 不可计算的问题
- 10.7 练习
- 第 11 章 计算+X
- 11.1 计算数学
- 11.2 生物信息学
- 11.3 计算物理学
- 11.4 计算化学
- 11.5 计算经济学
- 11.6 练习
- 附录
- 1 Python 异常处理参考
- 2 Tkinter 画布方法
- 3 Tkinter 编程参考
- 3.1 构件属性值的设置
- 3.2 构件的标准属性
- 3.3 各种构件的属性
- 3.4 对话框
- 3.5 事件
- 参考文献