Bootstrap

tkinter canvas绘图全攻略(图形项、配置参数和案例详解)

正在尝试着做一个比较完善的画图软件,计划使用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控件功能很强大,后续的绘图软件将会使用到上述的技术进行建设,敬请期待和关注!也欢迎关注我的公众号(俊哥随笔),一起共同成长!

;