这节课我们接着来讲解 Canvas 组件,既然 Cnavas 是画布的意思,那我们能不能让这个组件来设计一个画板呢?像Windows 自带的画图程序,我们的用户可以在上面随心所欲的绘制自己想要的图画,大家仔细想想,其实画图程序的实现原理很简单,就是通过获取用户拖拽鼠标时候的每一个位置(每个坐标),然后每个坐标对应绘制上一个点就可以了。这就提供了用户进行自由的绘制,但是有一点,tkinter 并没有提供支持画点的方法,但是呢,我们可以通过绘制一个超小的圆来表示一个点。
我们来实现一下:
-
import tkinter as tk
-
root = tk.Tk()
-
w = tk.Canvas(width = 400, height = 200)
-
w.pack()
-
def paint(event):
-
x1, y1 = (event.x -1), (event.y -1)
-
x2, y2 = (event.x +1), (event.y +1)
-
w.create_oval(x1,y1,x2,y2, fill = "red")
-
w.bind("<B1-Motion>", paint)
-
tk.Label(root, text = "按住鼠标左键并拖拽,绘制你的理想蓝图吧......").pack(side = "bottom")
-
root.mainloop()
关于 Cnavas,有些概念我认为你们需要理解,(温馨提示一下,如果对各个组件还有什么不懂的,可以直接看我整理的各组件的详解。)
Carvas 组件支持一些对象:
- arc(弧形、弦或扇形)
- bitmap(内建的位图文件或 XBM 格式的文件)
- image(BitmapImage 或 PhotoImage 的实例对象)
- line(线)
- oval(圆或椭圆形)
- polygon(多边形)
- rectangle(矩形)
- text(文本)
- window(组件)
其中,弦、扇形、椭圆形、圆形、多边形和矩形这些“封闭式”图形都是由轮廓线(outline)和填充(fill)颜色组成的,但都可以设置为透明(传入空字符串表示透明)。
Canvas 组件可以选择使用两种坐标系:
- 窗口坐标系:以窗口的左上角作为坐标原点
- 画布坐标系:以画布的左上角作为坐标原点
将窗口坐标系转换为画布坐标系,可以使用 canvasx() 或 canvasy() 方法。
画布对象显示的顺序
Canvas 组件中创建的画布对象都会被列入显示列表中,越接近背景的画布对象位于显示列表的越下方。显示列表决定当两个画布对象重叠的时候是如何覆盖的(默认情况下新创建的会覆盖旧的画布对象的重叠部分,即位于显示列表上方的画布对象将覆盖下方那个)。当然,显示列表中的画布对象可以被重新排序。
指定画布对象
Canvas 组件提供几种方法让你指定画布对象:
- Item handles
- Tags
- "all"
- "current"
ndles 事实上是一个用于指定某个画布对象的整型数字(也成为画布对象的 ID)。当你在 Canvas 组件上创建一个画布对象的时候,Tkinter 将自动为其指定一个在该 Canvas 组件中独一无二的整型值。然后各种 Canvas 的方法可以通过这个值操纵该画布对象。
Tags 是附在画布对象上的标签,Tags 由普通的非空白字符串组成。一个画布对象可以与多个 Tags 相关联,一个 Tag 也可用于描述多个画布对象。然而,与 Text 组件不同,没有指定画布对象的 Tags 不能进行事件绑定和配置样式。也就是说,Canvas 组件的 Tags 是仅为画布对象所拥有。
Canvas 组件预定义了两个 Tags:"all" 和 "current"
"all" 表示 Canvas 组件中的所有画布对象
"current" 表示鼠标指针下的画布对象(如果有的话)
画一个 哆啦A梦:(相信大家只要有耐心,好好计算坐标点,都能够画出来的)
-
import tkinter as tk
-
root = tk.Tk()
-
#画板
-
w = tk.Canvas(root, width=600, height=600, background="white")
-
w.pack()
-
#使用RGB颜色设计浅蓝色
-
Light_blue ="#%02x%02x%02x" % (0, 159, 232)
-
#头的轮廓蓝色
-
w.create_oval(150, 100,450,400,outline="black",fill=Light_blue)
-
#脸的白色
-
w.create_oval(175, 150,425,400,outline="black",fill="white")
-
#眼睛,椭圆,白色,先左后右
-
w.create_oval(250,115,300,180,outline="black",fill="white")
-
w.create_oval(300,115,350,180,outline="black",fill="white")
-
#眼睛 ==》》黑色,椭圆,先左后右
-
w.create_oval(280,137,295,159,outline="black",fill="black")
-
w.create_oval(305,137,320,159,outline="black",fill="black")
-
#眼睛==》》白色,椭圆,先左后右
-
w.create_line(287.5,145,287.5,151,fill='white',width=3,capstyle='round')
-
w.create_line(312.5,145,312.5,151,fill='white',width=3,capstyle='round')
-
#脸上的竖线黑色
-
w.create_line(300,180,300,300,fill='black',width=1)
-
#胡须水平的部分黑色,先左后右
-
w.create_line(200,240,280,240,fill='black',width=1.5)
-
w.create_line(320,240,400,240,fill='black',width=1.5)
-
#胡须位于水平胡须下方的两根黑色,先左后右
-
w.create_line(210,280,280,260,fill='black',width=1.5)
-
w.create_line(320,260,390,280,fill='black',width=1.5)
-
#胡须位于水平胡须上方的两根黑色,先左后右,
-
w.create_line(210,200,280,220,fill='black',width=1.5)
-
w.create_line(320,220,390,200,fill='black',width=1.5)
-
#嘴巴部分黑色
-
w.create_arc(175,50,425,300,width=1,style="arc",start=240,extent=60)
-
#鼻子红色
-
w.create_oval(290, 170,310,190,outline="black",fill="red")
-
#胳膊,蓝色,从左至右
-
w.create_arc(-75, 325,265,665,width=1,start=35,extent=20,style="pieslice",outline='black',fill=Light_blue)
-
w.create_arc(335, 325,675,665,width=1,start=125,extent=20,style="pieslice",outline='black',fill=Light_blue)
-
#胳膊去圆心部分,白色,从左至右
-
w.create_arc(50, 450,140,540,width=1,start=35,extent=20,style="pieslice",outline='white',fill='white')
-
w.create_arc(460, 450,550,540,width=1,start=125,extent=20,style="pieslice",outline='white',fill='white')
-
#手,白色,从左至右
-
w.create_oval(120, 430,160,470,outline="black",fill="white")
-
w.create_oval(440, 430,480,470,outline="black",fill="white")
-
#身体蓝色部分
-
w.create_rectangle(188,350,412,550,fill=Light_blue,outline="black")
-
#腹部的圆,白色
-
w.create_oval(215, 340,385,510,outline="white",fill="white")
-
#脖子上的横线红色部分
-
w.create_line(188,350,412,350,fill='red',width=15,capstyle='round')
-
#腹部的半圆,白色
-
w.create_arc(240, 365,360,485,width=1,start=180,extent=180,style="pieslice",outline='black',fill='white')
-
#两脚中间的扇形 白色
-
w.create_arc(280, 530,320,570,width=1,start=0,extent=180,style="pieslice",outline='white',fill='white')
-
#两只脚,椭圆,白色
-
w.create_oval(170, 530,290,570,outline="black",fill="white")
-
w.create_oval(310, 530,430,570,outline="black",fill="white")
-
#铃铛部分,黄色
-
w.create_oval(286, 346,314,374,outline="black",fill="yellow")
-
#铃铛的横线,黄色,使用矩形
-
w.create_rectangle(286,357,314,361,fill="yellow",outline="black")
-
#铃铛上的小红圆
-
w.create_oval(297, 363,303,369,outline="black",fill="red")
-
#脸上的竖线黑色
-
w.create_line(300,369,300,374,fill='black',width=1)
-
root.mainloop()
在这里我学会的一点就是:
如何在 tkinter 中使用自定义的 RGB 颜色:
语法如下:
define_color ="#%02x%02x%02x" % (0, 159, 232)
上面这一行代码的意思就是 创建一个名为 define_color 的变量,存取RGB 分别为 0,159,232 的颜色。
在后面就是直接使用 define_color,如:background = define_color,不需要加引号了。