Canvas(画布)组件为 Tkinter 的图形绘制提供了基础。Canvas 是一个高度灵活的组件,你可以用它绘制图形和图表,创建图形编辑器,并实现各种自定义的小部件。
--随心所欲绘制图像
Canvas(root, width=100, height=100) 单位像素
创建的对象一直保留,直到被修改才会覆盖
修改方法:
w.coords() 移动对象
w.itemcofig() 设置对象属性
w.delete() 删除对象
Canvas 组件支持对象
其中,弦、扇形、椭圆形、圆形、多边形和矩形这些“封闭式”图形都是由轮廓线和填充颜色组成的,但都可以设置为透明(传入空字符串表示透明)。
常用创建方法:
Create_line(x1,y1,x2,y2,dash=(4,4), fill='blue') -- 直线, 虚线(指定dash)
Create_rectangle() -- 矩形,添加对角坐标
Create_oval() -- 椭圆,使用的是长方形的坐标绘制的,正方形坐标时就是圆形
Create_text(x,y, text='F') --字体中心点坐标
create_arc(bbox, **options) -- 根据 bbox (x1, y1, x2, y2) 创建一个扇形(PIESLICE)、弓形(CHORD)或弧形(ARC)
style |
1. 指定该方法创建的是扇形(PIESLICE)、弓形(CHORD)还是弧形(ARC) 2. 默认创建的是扇形 |
create_polygon(coords, **options) -- 根据 coords 给定的坐标绘制一个多边形
坐标系
由于画布可能比窗口大(带有滚动条的 Canvas 组件),因此 Canvas 组件可以选择使用两种坐标系:
将窗口坐标系转换为画布坐标系,可以使用 canvasx() 或 canvasy() 方法:
def callback(event):
canvas = event.widget
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
print canvas.find_closest(x, y)
对象显示顺序:
Canvas 组件中创建的画布对象都会被列入显示列表中,
默认情况下新创建的会覆盖旧的画布对象的重叠部分,即位于显示列表上方的画布对象将覆盖下方那个)。当然,显示列表中的画布对象可以被重新排序。
指定画布对象
Canvas 组件提供几种方法让你指定画布对象:
EG: 简单的创作及修改
from tkinter import *
root = Tk()
w = Canvas(root, width=480, height=320, background='gray')
w.pack()
line = w.create_line(0, 50, 400, 50, dash=(4,4), fill='yellow')
rect = w.create_rectangle(120, 80, 360, 240, outline='red')
oval = w.create_oval(120, 80, 360, 240, fill='pink')
text = w.create_text(240, 160, text='Chick')
w.coords(line, 50, 50, 400, 100)
w.itemconfig(rect, fill='blue')
w.delete(oval)
mainloop()
EG: 绘制五角星(outline , fill)
"2 * PI / 5" 是用弧度的方式表示的。
Note: 关于弧度和度的区别
“度”的定义是,“两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧。当这段弧长正好等于圆周长的360分之一时,两条射线的夹角的大小为1度。(如图1)
“弧度”的定义是:两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧。当这段弧长正好等于圆的半径时,两条射线的夹角大小为1弧度。(如图2)
定义相似,区别仅在于角所对的弧长大小不同。1度的对应的弧长是等于圆周长的360分之一,而1弧度的是等于半径。
它们的关系可用下式表示和计算:
角(弧度)=弧长/半径
圆的周长是半径的 2π倍,所以一个周角(360度)是 2π弧度。
半圆的长度是半径的 π倍,所以一个平角(180度)是 π弧度。
<参考自弧度与角度的关系 - 简书>
from tkinter import *
import math as m
root = Tk()
w = Canvas(root, width=480, height=320, background='red')
w.pack()
# 圆心(x, y)和半径r
def draw_star(r, x, y):
# 各个点的坐标
points = [
# 左上角
x-int(r * m.sin(2 * m.pi / 5)), \
y-int(r * m.cos(2 * m.pi / 5)), \
# 右上角
x+int(r * m.sin(2 * m.pi / 5)), \
y-int(r * m.cos(2 * m.pi / 5)), \
# 左下角
x-int(r * m.sin(m.pi / 5)), \
y+int(r * m.cos(m.pi / 5)), \
# 顶点
x, \
y-r, \
# 右下角
x+int(r * m.sin(m.pi / 5)), \
y+int(r * m.cos(m.pi / 5)), \
]
star = w.create_polygon(points, fill='yellow')
draw_star(96, 160, 160)
draw_star(32, 320, 64)
draw_star(32, 384, 128)
draw_star(32, 384, 224)
draw_star(32, 320, 288)
mainloop()
真正标准的应该是这个样子的, 哈哈,下次在实现(我看大家都是用的turtle画的,下次再试)
EG: 制作画板
Tips: 通过最小正方形创建小圆点(Canvas 不能直接画点), 绑定鼠标左键 bind(
from tkinter import *
import math as m
root = Tk()
w = Canvas(root, width=500, height=400)
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')
# 绑定鼠标左键事件(mouse B1-left,B2-middle,B3-right)
w.bind('', paint)
# 创建一个按钮清除画板
Button(root, text='CLEAR', command=lambda x=ALL:w.delete(x)).pack(side=BOTTOM)
Label(root, text='Please hold the mouse button and move!').pack(side=BOTTOM)
mainloop()
''' Draw a Doraemon '''
from tkinter import *
import math as m
root = Tk()
w = Canvas(root, width=450, height=450, background='white')
w.pack()
def oval(x1, y1, x2, y2, color):
w.create_oval(x1, y1, x2, y2, fill=color)
def line(x1, y1, x2, y2, color):
w.create_line(x1, y1, x2, y2, fill=color)
def rect(x1, y1, x2, y2, color):
w.create_rectangle(x1, y1, x2, y2, fill=color)
# Head
oval(140, 90, 320, 270, 'blue')
# face
oval(160, 130, 300, 270, 'white')
# eyes
oval(200, 100, 230, 140, 'white')
oval(230, 100, 260, 140, 'white')
oval(215, 110, 225, 130, 'black')
oval(235, 110, 245, 130, 'black')
oval(218, 115, 222, 127, 'white')
oval(238, 115, 242, 127, 'white')
# nose
oval(223, 135, 238, 150, 'red')
# whisker
line(175, 150, 210, 160, 'black')
line(245, 160, 280, 150, 'black')
line(170, 175, 210, 175, 'black')
line(245, 175, 285, 175, 'black')
line(175, 200, 210, 190, 'black')
line(245, 190, 280, 200, 'black')
line(230, 150, 230, 220, 'black')
# mouth
w.create_arc(165, 100, 300, 220, style=ARC, start=225)
# body
rect(165, 240, 295, 370, 'blue')
oval(180, 235, 280, 335, 'white')
w.create_arc(190, 260, 270, 320, fill='', style=ARC, start=180)
w.create_arc(190, 260, 270, 320, fill='', style=ARC, start=270)
line(190, 290, 270, 290, 'black')
# neck
w.create_line(160, 240, 300, 240, width=15, fill='red', capstyle=ROUND)
# ring
oval(220, 240, 240, 260, 'yellow')
w.create_line(220, 250, 240, 250)
w.create_line(220, 252, 240, 252)
oval(227, 255, 232, 260, 'black')
# feet
oval(150, 350, 220, 390, 'white')
oval(240, 350, 310, 390, 'white')
w.create_arc(215, 365, 245, 430, style=CHORD, start=45, fill='white')
line(215, 375, 245, 375, 'white')
# left hand
w.create_polygon(167, 245, 130, 280, 130, 300, 167, 280, fill='blue')
oval(110, 280, 140, 310, 'white')
# right hand
w.create_polygon(293, 245, 325, 280, 325, 300, 293, 280, fill='blue')
oval(315, 280, 345, 310, 'white')
# body fixes
line(165, 270, 165, 290, 'black')
line(295, 270, 295, 290, 'black')
mainloop()