19、Canvas
本章将介绍tkinter模块内Canvas,这个模块可以绘图,也可以制作动画,而动画也是设计游戏的基础,本章将完整介绍这方面的知识。
19-1 绘图功能
19-1-1 建立画布
可以使用Canvas()方法建立画布对象。
python
tk = Tk() # 使用tk当窗口Tk对象
canvas = Canvas(tk, width=xx, height=yy) # xx,yy是画布的宽与高
canvas.pack() # 可以将画布包装好,这是必要的
画布建立完成后,左上角是坐标(0, 0),向右x轴递增,向下y轴递增。
19-1-2 绘制线条createline()
它的使用方式如下。
python
create_line(x1, y1, x2, y2, ..., xn, yn, option)
线条将会沿着(x1, y1), (x2, y2), ...绘制下去,下列是常用的options用法。
(1) arrow:默认是没有箭头,使用arrow=tk.FIRST在起始线末端有箭头,arrow=LAST在最后一条线末端有箭头,使用arrow=tk.BOTH在两端有箭头。
(2) arrowshape:使用元组(d1, d2, d3)代表箭头,默认是(8, 10, 3)。

(3) capstyle:这是线条终点的样式,默认是BUTT,也可以选择PROJECTING,ROUND,程序实例可以参考ch19_4。
(4) dash:建立虚线,使用元组储存数字数据,第一个数字是实线,第二个数字是空白,如此循环当所有元组数字用完又重新开始。例如,dash=(5, 3)产生5像素实现,3像素空白,如此循环。再如,dash=(8, 1, 1, 1),产生8像素实线和点的线条,dash=(5, )产生5像素实线5像素空白。
(5) dashoffset:与dash一样产生虚线,但是一开始数字是空白的宽度。
(6) fill:设置线条颜色。
(7) joinstyle:线条相交的设置,默认是ROUND,也可以选择BEVEL、MITER,程序实例可以参考ch19_3。
(8) stipple:绘制位图(Bitmap)线条,可以参考2-8节,程序实例可以参考ch19_5。
(9) width:线条宽度。
程序实例ch19_1:在半径为100的圆外围建立12个点,然后将这些点彼此连接。
python
from tkinter import *
import math
tk = Tk()
canvas = Canvas(tk, width=640, height=480)
canvas.pack()
x_center, y_center, r = 320, 240, 100
x, y = [], []
for i in range(12): # 建立圆外围12个点
x.append(x_center + r * math.cos(30*i*math.pi/180))
y.append(y_center + r * math.sin(30*i*math.pi/180))
for i in range(12): # 画出12条线段
for j in range(12):
canvas.create_line(x[i], y[i], x[j], y[j])
tk.mainloop()
执行结果

上述程序使用了数学函数sin()和cos()以及pi,这些是在math模块。使用create_line()时,在options参数字段可以用fill设置线条颜色,用width设置线条宽度。
程序实例ch19_2:用不同线条颜色与宽度。
python
from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=640, height=480)
canvas.pack()
canvas.create_line(100, 100, 500, 100)
canvas.create_line(100, 125, 500, 125, width=5)
canvas.create_line(100, 150, 500, 150, width=10, fill="blue")
canvas.create_line(100, 175, 500, 175, dash=(10, 2, 2, 2))
tk.mainloop()
执行结果

程序实例ch19_3:由线条交接了解joinstyle参数的应用。
python
# ch19_.py
from tkinter import *
import math
tk = Tk()
canvas = Canvas(tk, width=640, height=480)
canvas.pack()
canvas.create_line(30, 30, 500, 30, 265, 100, 30, 30,
width=20, joinstyle=ROUND)
canvas.create_line(30, 130, 500, 130, 265, 200, 30, 130,
width=20, joinstyle=BEVEL)
canvas.create_line(30, 230, 500, 230, 265, 300, 30, 230,
width=20, joinstyle=MITER)
tk.mainloop()
执行结果

程序实例ch19_4:由线条了解capstyle参数的应用。
python
# ch19_.py
from tkinter import *
import math
tk = Tk()
canvas = Canvas(tk, width=640, height=480)
canvas.pack()
canvas.create_line(30, 30, 500, 30, width=10, capstyle=BUTT)
canvas.create_line(30, 130, 500, 130, width=10, capstyle=ROUND)
canvas.create_line(30, 230, 500, 230, width=10, capstyle=PROJECTING)
# 以下垂直线
canvas.create_line(30, 20, 30, 240)
canvas.create_line(500, 20, 500, 250)
tk.mainloop()
执行结果

程序实例ch19_5:建立位图线条。
python
# ch19_.py
from tkinter import *
import math
tk = Tk()
canvas = Canvas(tk, width=640, height=480)
canvas.pack()
canvas.create_line(30, 30, 500, 30, width=10, stipple="gray25")
canvas.create_line(30, 130, 500, 130, width=40, stipple="questhead")
canvas.create_line(30, 230, 500, 230, width=10, stipple="info")
tk.mainloop()
执行结果

19-1-3 绘制矩形createrectangle()
它的使用方式如下。
python
create_rectangle(x1, y1, x2, y2, option)
(x1, y1)和(x2, y2)是矩形左上角和右下角的坐标,下列是·常用的options用法。
(1) dash:建立虚线,与create_lin()相同。
(2) dasgoffset:与fash一样产生虚线,但是一开始数字是空白的宽度。
(3) fill:矩形填充颜色。
(4) outline:设置矩形线条颜色。
(5) stipple:绘制位图矩形,可以参考2-8节,程序实例可以参考ch19_5。
(6) width:矩形线条宽度。
程序实例ch19_6:在画布内随机产生不同位置与大小的矩形。
python
# ch19_.py
from tkinter import *
from random import *
tk = Tk()
canvas = Canvas(tk, width=640, height=480)
canvas.pack()
for i in range(50): # 随机绘制50个不同位置与大小的矩形
x1, y1 = randint(1, 640), randint(1, 480)
x2, y2 = randint(1, 640), randint(1, 480)
if x1 > x2 : x1, x2 = x2, x1 # 确保左上角x坐标小于右下角x坐标
if y1 > y2 : y1, y2 = y2, y1 # 确保左上角y坐标小于右下角y坐标
canvas.create_rectangle(x1, y1, x2, y2)
tk.mainloop()
执行结果

这个程序每次执行时都会产生不同的结果,有一点儿艺术画的效果。使用create_rectangle()时,在options参数字段可以用fill='color'设置矩形填充颜色,用outline='color'设置矩形轮廓颜色。
程序实例ch19_7:绘制三个矩形,第一个使用红色填充轮廓是默认设置,第二个使用黄色填充轮廓是蓝色。第三个使用绿色填充轮廓是灰色。
python
# ch19_.py
from tkinter import *
from random import *
tk = Tk()
canvas = Canvas(tk, width=640, height=480)
canvas.pack()
canvas.create_rectangle(10, 10, 120, 60, fill='red')
canvas.create_rectangle(130, 10, 200, 80, fill='yellow')
canvas.create_rectangle(210, 10, 300, 60, fill='green')
tk.mainloop()
执行结果

由执行结果可以发现,由于画布底色是浅灰色,所以第三个矩形用灰色轮廓,几乎看不到轮廓线,另外也可以用width设置矩形轮廓的宽度。
19-1-4 绘制圆弧createarc()
它的使用方式如下。
python
create_arc(x1, y1, x2, y2, extent=angle, style=ARC, options)
(x1, y1)和(x2, y2)分别是圆弧左上角和右下角的坐标,下列是常用的options用法。
(1) dash:建立虚线,与create_line()相同。
(2) dashoffset:与dash一样产生虚线,但是一开始数字是空白的宽度。
(3) extent:如果是绘制圆形extent值是359,如果写成360会使为0°。如果extent介于1 ~ 359,则是绘制这个角度的圆弧。
(4) fill:填充圆弧颜色。
(5) outline:设置圆弧线条颜色。
(6) start:圆弧起点位置。
(7) stipple:绘制位图圆弧。
(8) style:有三种格式------ARC、CHORD、PIESLICE,可参考ch19_9。
(9) width:圆弧线条宽度。
上述style=ARC表示绘制圆弧,如果是要使用options参数填满圆弧则须舍去此参数。此外,options参数可以使用width设置轮廓线条宽度(可参考下列ch19_8第12行),outline设置轮廓线条颜色(可参考下列ch19_8的第15行),fill设置填充颜色(可参考下列ch19_8第10行)。目前默认绘制圆弧的起点是右边,也可以用start=0代表。也可以设置start的值更改圆弧的起点,方向是逆时针,可参考ch19_8第13行。
程序实例ch19_8:绘制各种不同的圆和椭圆,以及圆弧和椭圆弧。