当前位置:首页 » tkinter » 正文

tkinter的Canvas组件,绘画基本知识

Canvas组件,可以用来绘图,也可以用来制作动画,绘图,可以绘线条,圆,方形,多边形,制作动画,这是制作游戏的基础。

Canvas组件要学习的东西很多,参数也多,我觉得,我们可以先学一些基础的东西,等了解基础知识后,再深入学习。

Canvas组件,既然画线,画方框,画多边形,画圆,画文字,画组件等对象,你可以把Canvas组件当成容器组件来看待,先用“画”的方式来在画布里创建线,圆,框,文字,组件等,然后,再可经为这个组件设置各种属性:如更改坐标,改变颜色,当然你可以删除这些对象。

首先,我们先来学习如何如何创建画布,即Canvas组件。

 语法:Canvas(父组件,参数…….

先创建 一个浅蓝画布看看 

from tkinter import *
 
root=Tk()
 
can1=Canvas(root,width=200,height=150,background='lightblue')  # 浅蓝画布
 
can1.pack()
 
root.mainloop()

运行结果生成一个浅蓝色的画布(默认的画布背景颜色是跟窗体背景颜色是一样的,不太好辨认边界)

 

绘制线条:

create_line(x1, y1, x2, y2, …… xn,yn, 参数)

 

(X1,Y1)(x2,y2) ……. (xn,yn)  是不同点的坐标,画线的过程就是 (X1,Y1),连接 (x2,y2),再连接(x3,y3) …….再连接 (xn,yn)

 

参数:

arrow :

arrow=FIRST 起始点有箭头  arrow=LAST 最后一条线的末端有箭头

arrow=BOTH 2端都有箭头   默认是没有箭头

   

capstyle:

    线条末端的样式:BUTT,  PROJECTING,  ROUND  默认为BUTT

 

dash:

    画的线为虚线,虚线信息由元组来表现,元组的第1个数字为实线像素,第2个为空白像素,实线和空白交替使用元组的数字,用完后,再重新使用元组的第1个数字。如:

dash(5,1,1,1) 5像素的实线,1像素的空白,1像素的实线,1像素的空白

 

stipple: 绘制位图线条

widht : 线条宽度(粗细)

fill : 线条颜色

 

下面的代码来演示一下上面参数。

from tkinter import *
 
root=Tk()
 
can1=Canvas(root,width=220,height=150,background='lightblue') # 浅蓝画布
can1.pack(fill=BOTH,expand=True) 
 
can1.create_line(20,10,200,10) # 默认粗细线条
can1.create_line(20,35,200,35,width=5) # 粗线
can1.create_line(20,60,200,60,width=10,fill='red') # 红线
can1.create_line(20,85,200,85,dash=(5,2)) # 虚线
can1.create_line(20,110,200,110,arrow=BOTH) # 2端有箭头
can1.create_line(20,135,200,135,stipple='questhead',width=15) # 位图线
 
root.mainloop()

运行结果

      1.PNG

 

绘制矩形:

create_rectangle(x1,y1, x2,y2, 参数)

 

(x1,y1) x2,y2)是矩形的左上角和右下角的坐标,由2个坐标决定矩形的大小。

 

参数:

dash: 矩形线条为虚线

fill :  矩形填充颜色

outline:矩形线条颜色

stipple:位图填充矩形

width: 矩形线条宽度

from tkinter import *
 
root=Tk()
 
can1=Canvas(root,width=220,height=150,background='lightblue') # 浅蓝画布
can1.pack(fill=BOTH,expand=True) 
 
can1.create_rectangle(30,10,90,60,fill='red',outline='green',width=4)  # 左上图
 
can1.create_rectangle(130,10,200,60,dash=(3,2)) # 右上图
 
can1.create_rectangle(20,80,100,140,stipple='questhead',
     fill='red', outline='blue',width=2) # 左下图
 
can1.create_rectangle(120,80,210,140,stipple='questhead',
     fill='blue', outline='red',width=2,dash=(3,2)) # 右下图
 
root.mainloop()

运行结果

2.PNG

 

绘制圆弧:

create_arc( x1,y1, x2,y2, extent=angle, sytle=ARC, 参数 )

 

(x1,y1) x2,y2)决定一个矩形的左上角和右下角的坐标,而这个矩形决定圆弧的形状(弧度)。

extent: 跨度,即从圆弧的起始益到结束位置的角度,默认为90,范围是1359

style: 样式:扇形(‘pieslice’)  弓形(‘chord’) 弧形(‘arc’)  默认扇形

dash: 虚线

fill : 填充颜色

outline :圆弧线条颜色

start : 圆弧起始位置,默认益是圆弧的右边开始,方向是逆时针

stipple : 位图圆弧

width : 圆弧线条宽度(粗细)

 

其实create_arc() 方法可以创建:圆,圆弧,椭圆,椭圆弧。


(x1,y1) x2,y2)坐标来决定的是画圆和圆弧还是画椭圆及椭圆弧 

如果由这2对坐标参数决定的是一个正方形,那创建的就是这个正方形内的内切圆或圆弧;

如果由这2对坐标参数决定的是一个长方形,那创建的就是这个长方形内的内切椭圆或椭圆弧;


我来自wb86.com何老师的济亨网

下面的代码先画一个正方形,然后根据最上面的3项设置,用正方式同样的坐标画圆,圆弧,弓形,扇形,大家感受一下。 丶丌皛

from tkinter import *
 
root=Tk()
 
fr1=Frame(root,relief='ridge',borderwidth=1) # 不设置边线宽,无法显示
fr1.pack(fill=X)
fr2=Frame(root,relief='ridge',borderwidth=1) # 不设置边线宽,无法显示
fr2.pack()
 
var1=StringVar()
op1=OptionMenu(fr1,var1,'弓形','弧形','扇形').pack(side=LEFT,padx=20)
var1.set('弧形')
 
sca1=Scale(fr1,from_=0,to=359,orient=HORIZONTAL,label='起始偏移角度')
sca1.pack(side=LEFT,padx=20)
 
sca2=Scale(fr1,from_=0,to=359,orient=HORIZONTAL,label='圆心度(弧的跨度)')
sca2.pack(side=LEFT,padx=20)
 
def ok():
    can1.delete('all')  # 清除所有对象
    can1.create_rectangle(50,10,180,140,dash=(3,2)) # 画 正方形
    can1.create_line(115,0,115,150,dash=(3,2),fill='yellow') # 画 水平中线
    can1.create_line(40,75,190,75,dash=(3,2),fill='yellow') # 画 垂直中线
 
    a=var1.get()
    if a=='弓形':
        b='chord'
    elif a=='弧形':
        b='arc'
    elif a=='扇形':
        b='pieslice'
 
    can1.create_arc(50,10,180,140,style=b,start=sca1.get(),extent=sca2.get(),outline='red',width=4)
    # 根据参数的不同,生成不同的圆,圆弧(弓形,扇形)
 
but1=Button(fr2,text=" 画:圆、弧线 ",command=ok)
but1.pack()
 
can1=Canvas(fr2,width=220,height=150,background='lightblue') # 浅蓝画布
can1.pack(fill=BOTH,expand=True) 
 
ok()
 
root.mainloop()

运行后,调节3个参数的值,会出现不同形状,位置的圆弧。

3.PNG

圆心角调整到359度,就显示一个圆,但这个圆只有359度,仔细看,有缺角的。如果你调整到360度,其实就是0度,就什么都画不出来。

 

以下随便是选取一个偏移角度,再搭配弓形,扇形,画出来的图形。

注:水平黄线向右方向,是偏移0度,逆时针方向,可以0 - 359度偏移。

注意:fill 填充参数没有演示,这个参数填充颜色,只能是弓形和扇形才可以填充颜色。

 

举一反三,你可以把上面的代码,正方形的坐标改成长方形,就会画出椭圆,以及椭圆弧,在这里就不再演示了。

 

上面用画圆弧的方法画圆,其实只是一个大的圆弧,并不是真的圆,因为这个弧还是有一个缺口,现在我们来用新的方法画圆或椭圆。

 

绘制圆或椭圆:

create_oval( x1,y1, x2,y2, 参数 )

 

(x1,y1) x2,y2)坐标来决定的是画圆 还是画椭圆。

在这里的参数跟以上关于线条,弧度的参数相同,并没有太多的知识要讲,下面有代码来说明:

 
from tkinter import *
 
root=Tk()
 
can1=Canvas(root,width=270,height=150,background='lightblue') # 浅蓝画布
can1.pack()
 
can1.create_rectangle(20,10,150,140,dash=(3,2),outline='green') # 画 正方形
can1.create_oval(20,10,150,140,width=4,fill='lightyellow') # 画 圆,填充浅黄
 
can1.create_rectangle(160,10,250,140,dash=(3,2),outline='green') # 画 长方形
can1.create_oval(160,10,250,140,width=4,fill='lightgreen') # 画 椭圆,填充浅绿
 
root.mainloop()

 运行结果

6.PNG

 

绘制多边形:

create_polygon( x1,y1, x2,y2, …… xn,yn, 参数 )

 

上面的参数跟绘制线条很类似, 区别在于:

 

(X1,Y1)(x2,y2) ……. (xn,yn)  是不同点的坐标。

画线的过程就是 (X1,Y1),连接 (x2,y2),再连接(x3,y3) …….再连接 (xn,yn)

画多边形就是:按画线过程,从起始点连接到结束点,但是要多一步,就是把结束点再连接起始点。

 

下面的代码,在绘制多边形的同时,在它的下方也绘制线条,你就可以看到多边形要连接起始点和结束点,而且可以填充颜色。

from tkinter import *
 
root=Tk()
 
can1=Canvas(root,width=460,height=200,background='lightblue') # 浅蓝画布
can1.pack(fill=BOTH,expand=True) 
 
can1.create_polygon(10,10, 100,10, 50,80,fill='',outline='red') # 红框,透明填充
can1.create_line(10,100, 100,100, 50,180, fill='red') # 画线
 
can1.create_polygon(120,10, 180,30, 250,50, 200,80, 130,70, fill='lightyellow',outline='blue') # 蓝框,浅黄填充
can1.create_line(120,100, 180,120, 250,140, 200,170, 130,160 ,fill='blue') # 画线
 
can1.create_polygon(260,10, 370,30, 440,70, 380,90, 320,80, outline='green',width=5) # 绿框,默认为黑色填充
can1.create_line(260,110, 370,130, 440,170, 380,190, 320,180, fill='green',width=5) # 画线
 
root.mainloop()

 运行结果

7.PNG

fill=’’ 表示多边形填充的是透明色。如果没有写fill这个参数,默认是填充黑色。

 

绘制文字:

create_text( x,y, text=字符文本, 参数 )

 

(x,y) 是字符文本在画布的坐标位置,但文本的起始位置要根据参数 anchor 来决定。

anchor 这个参数跟以前学的标签组件的anchor一样,有"n", "ne", "e", "se", "s", "sw", "w", "nw", "center" 9个选项,默认是center这个居中选项。

fill : 字符文本的颜色。

font : 字符文本的字体,大小。

justify : 多行显示时,靠那一边对齐。默认是LEFT

width : 这个参数类似于标签组件的wraplength参数,它决定在什么位置字符文本换行。

stipple : 指定一个位图用于填充,如果是空字符串,即字体为实心。

 

下面代码来演示一下,坐标和anchor 2个参数来决定文本的显示位置

。
from tkinter import *
 
root=Tk()
 
can1=Canvas(root,width=240,height=100,background='lightblue') # 浅蓝画布
can1.pack(fill=BOTH,expand=True) 
 
can1.create_line(120,0, 120,100,fill='yellow') # 垂直中心线
can1.create_line(0,50, 240,50,fill='yellow') # 水平中心线
 
can1.create_text(120,50,text='中国在中间',font=('黑体',17,'bold'),fill='red') # anchor默认为center
can1.create_text(120,50,text='美国靠下边',font=('黑体',17,'bold'),fill='blue',anchor=NW)
 
root.mainloop()

运行结果:

8.PNG

“中国在中间”文本没有设置anchor参数,anchor默认为center,居中,这个文本的锚点是文本的正中间,正中间的坐标就是 x,y 这个坐标。

而“美国靠下边”这个文本,我设置anchor=NW,所以,这个文本的锚点为左上角,左上角的位置就是 x,y 这个坐标。

 

你只要把输入的文本当成一个标签组件的文本,整个画布当成这个标签的大小,就好理解了,anchor参数在画布以及标签组件的用法是一样的。

 

插入图片:

create_image( x,y, 参数 )

 (x,y) 是插入图片的坐标位置,但图片的位置要根据参数 anchor 来决定,这点跟上面的说的插入文本是完全一样的。

虽说是插入图片,你也可以当成是插入带图片的标签,所以插入的图片要先用 PhotoImage() 等方法来创建图片对象。

 

感觉没有太多的新知识要讲解,在这里就不用代码演示了。


插入组件:

create_window( x,y, 参数 )

(x,y) 坐标,anchor参数跟上面讲解知识完全一样。

window:这个参数又类似Text组件插入其他组件一样,插入的组件也一样可以响应事件。

 

下面的代码演示一下。

from tkinter import *
 
root=Tk()
 
can1=Canvas(root,width=240,height=100,background='lightblue') # 浅蓝画布
can1.pack(fill=BOTH,expand=True) 
 
can1.create_line(120,0, 120,100,fill='yellow') # 垂直中心线
can1.create_line(0,50, 240,50,fill='yellow') # 水平中心线
 
but1=Button(root,text="按钮",command=lambda:print('被点击了')) # 先创建按钮
ra1=Radiobutton(root,text='多选按钮') # 先创建多选按钮
 
can1.create_window(120,50,window=but1) # 在正中间插入按钮
can1.create_window(120,50,window=ra1,anchor=NW) # 插入多选按钮
 
root.mainloop()

运行结果:

9.PNG

 

下面是用代码来做一个简单的画图软件,这个软件可以设置画笔颜色,画笔粗细,清除画布。

代码里用到的颜色对话框,这个知识在以前的文章里讲解过了。

from tkinter import *
from tkinter.colorchooser import *
 
root=Tk() # 源码来自 wb98.com
 
fr1=Frame(root,relief='ridge',borderwidth=1) # 不设置边线宽,无法显示
fr1.pack(fill=X)
 
but1=Button(fr1,text="点击选择画笔颜色", relief='sunken', bg='red',
command=lambda:but1.config(bg=askcolor()[1])) # 点击弹出颜色对话框
but1.pack(side=LEFT,padx=20)
 
la1=Label(fr1,text='画笔粗细: ')
la1.pack(side=LEFT)
 
spin1=Spinbox(fr1,from_=1,to=20,width=6) # 画笔粗细
spin1.pack(side=LEFT)
 
but2=Button(fr1,text=" 清空画布 ",command=lambda:can1.delete('all')) # 清空画布
but2.pack(side=LEFT,padx=20)
 
can1 = Canvas(root,width=400, height=200,background='white') # 白底画布
can1.pack(fill=BOTH,expand=True)
 
def paint(event): # 鼠标点击画点 或 按下鼠标移动画线
    hb=int(spin1.get()) # hb是画笔的粗细
    x1, y1 = (event.x - hb), (event.y - hb)  # 圆的左上角坐标
    x2, y2 = (event.x + hb), (event.y + hb)  # 圆的右下角坐标
    can1.create_oval(x1, y1, x2, y2,fill=but1['bg'], outline=but1['bg']) # 画圆 连线
 
can1.bind("<B1-Motion>", paint) # 按下鼠标移动画画
can1.bind("<Button-1>",paint) # 点击鼠标右键画点
 
root.mainloop()

运行结果:

10.PNG

 

tkinter中没有画点的方法,在上述代码中,是以画圆的方法来画点的,最小的粗细的画笔就是圆的左上角坐标跟右下角坐标是一样的。

 

清除画面上的所有对象,用的方法是:delete('all')  所以,上面代码中用于清空画布的代码就是: can1. delete('all')

 

Canvas组件还有一些参数没有说明,我自己也要慢慢学习,再来讲解。


还有有关动画的方法也没有讲解,下一篇文章再简单地讲一下用Canvas组件动画初步。

此文章来自:wb98.com  网站还有相关的系列课程文章,感兴趣的可以前往。


打赏 支付宝打赏 微信打赏

来源:济亨网

本文链接:https://wb98.com/post/332.html

    << 上一篇 下一篇 >>

    湘公网安备 43011102000514号 - 湘ICP备08100508号