正在尝试着做一个比较完善的画图软件,计划使用tkinter库中的canvas控件来做,然后正在攻关canvas控件的相关知识,因此作为这个画图软件的附带产出物,整理成了本篇博文,分享给大家,一起研究研究,期待能对你工作带来启发和帮助。
不忘初心,方得始终,让我们一起共勉!
好的,言归正传,回归本篇博文的主题:tkinter canvas绘图全攻略(图形项、配置参数和案例详解)
Tkinter提供了Canvas 控件来实现绘图,在 Canvas 中可以绘制直线、矩形、椭圆等各种几何图形,也可绘制图片、文字、UI 组件(如 Button)等。Canvas 允许重新改变这些图形的属性,比如改变其坐标、外观、大小、位置等。
(一)图形绘制
Canvas 组件的用法与其他 GUI 组件一样简单,程序只要创建并添加 Canvas 组件,然后调用该组件的方法来绘制图形即可。
from tkinter import *
root =Tk()
root.title('我的第一个canvas窗口')
cv =Canvas(root,width=500,height=500)
cv.pack(fill=BOTH, expand=YES)
oval1 = cv.create_oval(100,100,300,300,
outline='yellow',# 边框颜色
fill='pink',# 填充颜色
width=4# 边框宽度
)
print(oval1)
root.mainloop()
运行效果如下:
Canvas 提供了 create_oval() 方法绘制椭圆(包括圆,圆是椭圆的特例)。 实际上,Canvas 还提供了如下方法来绘制各种图形:
create_rectangle() :绘制矩形
create_arc:绘制弧。
create_bitmap:绘制位图。
create_image:绘制图片。
create_line():绘制直线。
create_polygon:绘制多边形。
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,width=780,height=160,background='white')
cv.pack(fill=BOTH, expand=YES)
columnFont =('微软雅黑',18)
# 使用循环绘制文字
for i, st in enumerate(['默认选项','指定边宽','指定填充','边框颜色','位图填充']):
cv.create_text((50+ i *140,30),text = st,
font = columnFont,
fill='gray',
anchor = W,
justify = LEFT)
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):
cv.create_rectangle(50+ i *140,60,160+ i *140,120,
width = op[0],# 边框宽度
fill = op[1],# 填充颜色
outline = op[2],# 边框颜色
stipple = op[3])# 使用位图填充
root.mainloop()
运行效果如下:
二、不只是静态的图形
在 Canvas 中通过 create_xxx 方法绘制图形项之后,这些图形项井不是完全静态的图形,每个图形项都是一个独立的对象,程序完全可以动态地修改、删除这些图形项。
为了修改、删除这些图形项,程序需要先获得这些图形项的引用。
获得这些图形项的引用有两种方式:
1.通过图形项的 id,也就是 Canvas 执行 create_xxx() 方法的返回值。一般来说,create_xxx() 会依次返回 1、2、3 等整数作为图形项的 id。
2.通过图形项的 tag(标签)。
(一)TAG图形项配置
程序完全可以根据 tag 来新增、修改、获取或者操作图形项。
1、增加图形项:
addtag_all(self, newtag):为所有图形项添加新 tag。
addtag_closest(self, newtag, x, y):为和 x、y 点最接近的图形项添加新 tag。
addtag_enclosed(self, newtag, x1, y1, x2, y2):为指定矩形区域内最上面的图形项添加新tag。其中 x1、y1 确定矩形区域的左上角坐标;x2、y2 确定矩形区域的右下角坐标。
addtag_withtag(self, newtag, tagOrId):为 tagOrId 对应图形项添加新 tag。
2、删除图形项:
dtag(self, *args):删除指定图形项的tag。
3、获取图形项:
gettags(self, *args):获取指定图形项的所有tag。
find_withtag(self, tagOrId):获取tagOrId 对应的所有图形项。
4、操作图形项
在 Canvas 中获取图形项之后,接下来可通过 Canvas 提供的大量方法来操作图形项。
Canvas 以“堆叠”的形式来管理这些图形项,先绘制的图形项位于“堆叠”的下面,后绘制的图形项位于“堆叠”的上面。因此,如果两个图形项有重叠的部分,那么后绘制的图形项(位于上面)会遮挡先绘制的图形项。
总结起来,Canvas 提供了如下方法在图形项“堆叠”中查找图形项:
find_all(self):返回全部图形项。
find_closest(self, x, y):返回和 x 、y 点最接近的图形项。
find_enclosed(self, x1, y1, x2, y2):返回位于指定矩形区域内最上面的图形项。
find_overlapping(self, x1, y1, x2, y2):返回与指定矩形区域重叠的最上面的图形项。
find_withtag(self, tagOrId):返回 tagOrId 对应的全部图形项。
如果程序希望获取或修改图形项的选项,则可通过 Canvas 的如下方法来操作:
itemcget(self, tagOrId, option):获取tagOrId 对应图形项的option 选项值。
itemconfig(self, tagOrId, cnf=None, **kw):为tagOrId 对应图形项配置选项。
itemconfigure(self, tagOrId, cnf=None, **kw):该方法与上一个方法完全相同。
Canvas 提供了如下方法来改变图形项的大小和位置:
coords(self, *args):重设图形项的大小和位置。
move(self, *args):移动图形项,但不能改变大小。简单来说,就是在图形项的 x、y 基础上加上新的 mx、my 参数。
scale(self, *args):缩放图形项。该方法的 args 参数要传入 4 个值,其中前两个值指定缩放中心;后两个值指定 x、y 方向的缩放比。
(二)图形操作和事件响应
通过获取图形项的 id或者tag(标签),最大的目的就是可以对canvas上的图形获取到其引用,然后可以进行后续的相关操作(如改变图形的大小、进行移动、修改颜色等属性),但是具体如何操作,主要是根据我们自行设置的响应函数或者自带的默认响应函数相关,而且必须进行事件响应绑定。Canvas 提供了一个 tag_bind() 方法,该方法用于为指定图形项绑定事件处理函数或方法,这样图形项就可以响应用户动作了。
这里提供两个案例告诉大家如何操作tag_bind()方法进行事件绑定响应的。
案例一:矩形框事件响应
from tkinter import *
from tkinter import messagebox
def test(event):
messagebox.showinfo(message='你点击了矩形框!')
root =Tk()
root.title('我的第三个canvas窗口(tag_bind()绑定事件')
cv =Canvas(root,bg ='white')
cv.pack()
cv.create_rectangle(30,30,220,150,
width =8,outline='red',# 边框颜色
tags =('r1'),fill='pink')
# 为指定图形项的左键单击事件绑定处理函数
cv.tag_bind('r1','<Button-1>', test)
root.mainloop()
具体运行效果如下:
案例二:canvas图形框大小随着窗口变化而动态变化
from tkinter import *
def on_resize(event):
# determine the ratio of old width/height to new width/height
wscale = float(event.width) / cv.winfo_reqwidth()
hscale = float(event.height) / cv.winfo_reqheight()
cv.config(width=event.width,height=event.height)
cv.scale("all", 0, 0, wscale, hscale)
root =Tk()
root.title('我的第三个canvas窗口(resize窗口)')
cv =Canvas(root,width=500,height=500, highlightthickness=0)
cv.pack(fill=BOTH, expand=YES)
oval1 = cv.create_oval(150,150,350,350,
outline='yellow',# 边框颜色
fill='pink',# 填充颜色
width=4# 边框宽度
)
cv.addtag_all("all")
cv.bind("<Configure>", on_resize)
root.mainloop()
具体运行效果如下:
好的,这篇博文写完了,主要是对canvas的基础知识进行介绍,canvas控件功能很强大,后续的绘图软件将会使用到上述的技术进行建设,敬请期待和关注!也欢迎关注我的公众号(俊哥随笔),一起共同成长!