Python之tkinterCanvas操作
Python tkinter Canvas画布完全攻略
Tkinter 提供了 Canvas 组件来实现绘图。程序既可在 Canvas 中绘制直线、矩形、椭圆等各种⼏何图形,也可绘制图⽚、⽂字、UI 组件(如 Button)等。Canvas 允许重新改变这些图形项(Tkinter 将程序绘制的所有东西统称为 item)的属性,⽐如改变其坐标、外观等。
Canvas 组件的⽤法与其他 GUI 组件⼀样简单,程序只要创建并添加 Canvas 组件,然后调⽤该组件的⽅法来绘制图形即可。如下程序⽰范了最简单的 Canvas 绘图:
from tkinter import *
# 创建窗⼝
root = Tk()
# 创建并添加Canvas
cv = Canvas(root, background='white')
cv.pack(fill=BOTH, expand=YES)
outline='red', # 边框颜⾊
stipple = 'question', # 填充的位图
fill="red", # 填充颜⾊
width=5 # 边框宽度
)
outline='yellow', # 边框颜⾊
fill='pink', # 填充颜⾊
width=4 # 边框宽度
)
root.mainloop()
上⾯程序先创建并添加了 Canvas 组件,分别绘制了矩形和椭圆。运⾏上⾯程序,可以看到如图 1 所⽰的效果。
图 1 最简单的 Canvas 绘图
从上⾯程序可以看到,Canvas 提供了 create_rectangle() ⽅法绘制矩形和 create_oval() ⽅法绘制椭圆(包括圆,圆是椭圆的特例)。实际上,Canvas 还提供了如下⽅法来绘制各种图形:
create_arc:绘制弧。
create_bitmap:绘制位图。
create_image:绘制图⽚。
create_line():绘制直线。
create_polygon:绘制多边形。
create_text:绘制⽂字。
create_window:绘制组件。
Canvas 的坐标系统是绘图的基础,其中点 (0,0) 位于 Canvas 组件的左上⾓,X 轴⽔平向右延伸,Y 轴垂直向下延伸。
绘制上⾯这些图形时需要简单的⼏何基础:
在使⽤ create_line() 绘制直线时,需要指定两个点的坐标,分别作为直线的起点和终点。
在使⽤ create_rectangle() 绘制矩形时,需要指定两个点的坐标,分别作为矩形左上⾓点和右下⾓点的坐标。
在使⽤ create_oval() 绘制椭圆时,需要指定两个点的坐标,分别作为左上⾓点和右下⾓点的坐标来确定⼀个矩形,⽽该⽅法则负责绘制该矩形的内切椭圆,如图 2 所⽰。
图 2 内切椭圆
从图 2 可以看出,只要矩形确定下来,该矩形的内切椭圆就能确定下来,⽽ create_oval() ⽅法所需要的两个坐标正是⽤于指定该矩形的左上⾓点和右下⾓点的坐标。
在使⽤ create_arc 绘制弧时,和 create_oval 的⽤法相似,因为弧是椭圆的⼀部分,因此同样也是指定左上⾓和右下⾓两个点的坐标,默认总是绘制从 3 点(0)开始,逆时针旋转 90° 的那⼀段弧。程序可通过 start 改变起始⾓度,也可通过 extent 改变转过的⾓度。
在使⽤ create_polygon 绘制多边形时,需要指定多个点的坐标来作为多边形的多个定点;在使⽤ create_bitmap、create_image、create_text、create_window 等⽅法时,只要指定⼀个坐标点,⽤于指定⽬标元素的绘制位置即可。
在绘制这些图形时可指定如下选项:
fill:指定填充颜⾊。如果不指定该选项,默认不填充。
outline:指定边框颜⾊。
width:指定边框宽度。如果不指定该选项,边框宽度默认为 1。
dash:指定边框使⽤虚线。该属性值既可为单独的整数,⽤于指定虚线中线段的长度;也可为形如(5,2,3)格式的元素,此时5 指定虚线中线段的长度,2 指定间隔长度,3 指定虚线长度……依此类推。
stipple:使⽤位图平铺进⾏填充。该选项可与 fill 选项结合使⽤,fill 选项⽤于指定位图的颜⾊。
style:指定绘制弧的样式。该选项仅对 create_arc ⽅法起作⽤。该选项⽀持 PIESLICE(扇形)、CHORD(⼸形)、ARC(仅绘制弧)选项值。
start:指定绘制弧的起始⾓度。该选项仅对 create_arc ⽅法起作⽤。
extent:指定绘制弧的⾓度。该选项仅对 create_arc ⽅法起作⽤。
arrow:指定绘制直线时两端是否有箭头。该选项⽀持 NONE(两端⽆箭头)、FIRST(开始端有箭头)、LAST(结束端有箭头)、BOTH(两端都有箭头)选项值。
arrowshape:指定箭头形状。该选项是⼀个形如 "20 20 10" 的字符串,字符串中的三个整数依次指定填充长度、箭头长度、箭头宽度。 joinstyle:指定直接连接点的风格。仅对绘制直线和多向形有效。该选项⽀持 METTER、ROUND、BEVEL 选项值。
anchor:指定绘制⽂字、GUI 组件的位置。该选项仅对 create_text()、create_window() ⽅法有效。
justify:指定⽂字的对齐⽅式。该选项⽀持 CENTER、LEFT、RIGHT 常量值,该选项仅对 create_text ⽅法有效。
下⾯程序⽰范了通过不同的⽅法来绘制不同的图形,这些图形分别使⽤不同的边框、不同的填充效果:
from tkinter import *
# 创建窗⼝
root = Tk()
root.title('绘制图形项')
# 创建并添加Canvas
cv = Canvas(root, background='white', width=830, height=830)
cv.pack(fill=BOTH, expand=YES)
columnFont = ('微软雅⿊', 18)
titleFont = ('微软雅⿊', 20, 'bold')
# 使⽤循环绘制⽂字
for i, st in enumerate(['默认', '指定边宽', '指定填充', '边框颜⾊', '位图填充']):
font = columnFont,
fill='gray',
anchor = W,
justify = LEFT)
# 绘制⽂字
font = titleFont,
fill='magenta',
anchor = W,
justify = LEFT)
# 定义列表,每个元素的4个值分别指定边框宽度、填充⾊、边框颜⾊、位图填充
options = [(None, None, None, None),
(4, None, None, None),
(4, 'pink', None, None),
(4, 'pink', 'blue', None),
(4, 'pink', 'blue', 'error')]
# 采⽤循环绘制5个矩形
for i, op in enumerate(options):
width = op[0], # 边框宽度
fill = op[1], # 填充颜⾊
outline = op[2], # 边框颜⾊
stipple = op[3]) # 使⽤位图填充
# 绘制⽂字
font = titleFont,
fill='magenta',
anchor = W,
justify = LEFT)
# 定义列表,每个元素的4个值分别指定边框宽度、填充⾊、边框颜⾊、位图填充options = [(None, None, None, None),
(4, None, None, None),
(4, 'pink', None, None),
(4, 'pink', 'blue', None),
(4, 'pink', 'blue', 'error')]
# 采⽤循环绘制5个椭圆
for i, op in enumerate(options):
width = op[0], # 边框宽度
fill = op[1], # 填充颜⾊
outline = op[2], # 边框颜⾊
stipple = op[3]) # 使⽤位图填充
obang# 绘制⽂字
font = titleFont,
fill='magenta',
anchor = W,
justify = LEFT)
# 定义列表,每个元素的4个值分别指定边框宽度、填充⾊、边框颜⾊、位图填充options = [(None, "", 'black', None),
(4, "", 'black', None),
(4, 'pink', 'black', None),
(4, 'pink', 'blue', None),
(4, 'pink', 'blue', 'error')]
# 采⽤循环绘制5个多边形
for i, op in enumerate(options):
fill = op[1], # 填充颜⾊
outline = op[2], # 边框颜⾊
stipple = op[3]) # 使⽤位图填充
# 绘制⽂字
font = titleFont,
fill='magenta',
anchor = W,
justify = LEFT)
# 定义列表,每个元素的4个值分别指定边框宽度、填充⾊、边框颜⾊、位图填充options = [(None, None, None, None),
(4, None, None, None),
(4, 'pink', None, None),
(4, 'pink', 'blue', None),
(4, 'pink', 'blue', 'error')]
# 采⽤循环绘制5个扇形
for i, op in enumerate(options):
width = op[0], # 边框宽度
我回来了英文fill = op[1], # 填充颜⾊
outline = op[2], # 边框颜⾊
stipple = op[3]) # 使⽤位图填充
# 绘制⽂字
font = titleFont,
fill='magenta',
德福考试anchor = W,
justify = LEFT)
# 定义列表,每个元素的4个值分别指定边框宽度、填充⾊、边框颜⾊、位图填充
recruit是什么意思
options = [(None, None, None, None),
(4, None, None, None),
(4, 'pink', None, None),
(4, 'pink', 'blue', None),
(4, 'pink', 'blue', 'error')]
# 采⽤循环绘制5个⼸形
for i, op in enumerate(options):
width = op[0], # 边框宽度
fill = op[1], # 填充颜⾊
outline = op[2], # 边框颜⾊
stipple = op[3], # 使⽤位图填充
start = 30, # 指定起始⾓度
extent = 60, # 指定逆时针转过⾓度
style = CHORD) # CHORD指定绘制⼸
# 绘制⽂字
font = titleFont,
fill='magenta',
anchor = W,
justify = LEFT)
# 定义列表,每个元素的4个值分别指定边框宽度、填充⾊、边框颜⾊、位图填充
options = [(None, None, None, None),
(4, None, None, None),
(4, 'pink', None, None),
(4, 'pink', 'blue', None),
(4, 'pink', 'blue', 'error')]
# 采⽤循环绘制5个弧
for i, op in enumerate(options):
width = op[0], # 边框宽度
fill = op[1], # 填充颜⾊
outline = op[2], # 边框颜⾊
stipple = op[3], # 使⽤位图填充
2021年四级成绩什么时间公布
start = 30, # 指定起始⾓度
extent = 60, # 指定逆时针转过⾓度
style = ARC) # ARC指定仅绘制弧
version什么意思# 绘制⽂字
font = titleFont,
fill='magenta',
anchor = W,
justify = LEFT)
# 定义列表,每个元素的5个值分别指定边框宽度、线条颜⾊、位图填充、箭头风格, 箭头形状options = [(None, None, None, None, None),
(6, None, None, BOTH, (20, 40, 10)),
(6, 'pink', None, FIRST, (40, 40, 10)),
eliminate(6, 'pink', None, LAST, (60, 50, 10)),
(8, 'pink', 'error', None, None)]
# 采⽤循环绘制5个弧
for i, op in enumerate(options):
width = op[0], # 边框宽度
fill = op[1], # 填充颜⾊
stipple = op[2], # 使⽤位图填充
arrow = op[3], # 箭头风格
arrowshape = op[4]) # 箭头形状
# 绘制⽂字
font = titleFont,
fill='magenta',
anchor = W,
crushedjustify = LEFT)
# 定义包括create_bitmap, create_image, create_window三个⽅法的数组
funcs = [ate_bitmap, ate_image, ate_window]
# 为上⾯3个⽅法定义选项
items = [{'bitmap' : 'questhead'}, {'image':PhotoImage(file='images/fklogo.gif')},
{'window':Button(cv,text = '单击我', padx=10, pady=5,
command = lambda :print('按钮单击')),'anchor': W}]
for i, func in enumerate(funcs):
func(cv, 230 + i * 140, 780, **items[i])
root.mainloop()
上⾯程序⽰范了 Canvas 中不同的 create_xxx ⽅法的功能和⽤法,它们可⽤于创建矩形、椭圆、多边形、扇形、⼸形、弧、直线、位图、图⽚和组件等。在绘制不同的图形时可指定不同的选项,从⽽实现丰富的绘制效果。
运⾏上⾯程序,可以看到如图 3 所⽰的效果。
图 3 使⽤Canvas 绘制图形
掌握了上⾯的绘制⽅法之后,实际上已经可以实现⼀些简单的游戏了。⽐如前⾯介绍的控制台五⼦棋,之前程序是在控制台打印游戏状态的,实际上程序完全可以在界⾯上绘制游戏状态,这样就能看到图形界⾯的五⼦棋了。
此外,该五⼦棋还需要根据⽤户的⿏标动作来确定下棋坐标,因此程序会为游戏界⾯的 <Button-1>(左键单击)、<Motion>(⿏标移动)、<Leave>(⿏标移出)事件绑定事件处理函数。下⾯程序⽰范了实现图形界⾯的五⼦棋:
from tkinter import *
import random
BOARD_WIDTH = 535
BOARD_HEIGHT = 536
BOARD_SIZE = 15
# 定义棋盘坐标的像素值和棋盘数组之间的偏移距。
X_OFFSET = 21
Y_OFFSET = 23
# 定义棋盘坐标的像素值和棋盘数组之间的⽐率。
X_RATE = (BOARD_WIDTH - X_OFFSET * 2) / (BOARD_SIZE - 1)
Y_RATE = (BOARD_HEIGHT - Y_OFFSET * 2) / (BOARD_SIZE - 1)
BLACK_CHESS = "●"
WHITE_CHESS = "○"
board = []
# 把每个元素赋为"╋",代表⽆棋
for i in range(BOARD_SIZE) :
row = ["╋"] * BOARD_SIZE
board.append(row)
# 创建窗⼝
root = Tk()
# 禁⽌改变窗⼝⼤⼩
# 修改图标
root.iconbitmap('images/fklogo.ico')
# 设置窗⼝标题
root.title('五⼦棋')
# 创建并添加Canvas
cv = Canvas(root, background='white',
width=BOARD_WIDTH, height=BOARD_HEIGHT)
cv.pack()
bm = PhotoImage(file="images/board.png")
lectedbm = PhotoImage(file="images/lected.gif")
# 创建选中框图⽚,但该图⽚默认不在棋盘中
weexlected = cv.create_image(-100, -100, image=lectedbm)
def move_handler(event):
# 计算⽤户当前的选中点,并保证该选中点在0~14之间
lectedX = max(0, min(round((event.x - X_OFFSET) / X_RATE), 14))
lectedY = max(0, min(round((event.y - Y_OFFSET) / Y_RATE), 14))
# 移动红⾊选择框
参加英文