在前文tkinter-place详解中,讲解anchor属性时,用到了canvas。如果你不知道什么时canvas,精读本文就对了!
canvas的中文意思就是"画布"。在GUI中,canvas是一个非常基础的概念,基本上任何跟GUI相关的编程语言、库、框架等,都会有canvas,只要搞懂了canvas是什么,就一通百通了。
首先,我通俗的解释一下什么是canvas。就像画油画一样,得先准备一张画布,然后再在这张画布上进行创作,你可以在画布上画任何你想画的东西,直线、圆、椭圆等。在tkinter中,canvas就是类似的作用。提供给你一张"画布",你可以在上面"画"任何基础图形,也可以"画"其他控件。
canvas
Canvas(master, cnf={}, **kw)
想画画,通常要选择一个指定大小的画布,canvas可以通过属性width、height来选择canvas的尺寸。
width
指定 canvas的宽度
height
指定 canvas的高度
bg
指定 canvas的背景颜色
from tkinter import (Tk, Button, Canvas)
from tkinter.constants import RIGHT, LEFT, X, Y, BOTH
main_win = Tk()
main_win.title('渔道的canvas')
width = 300
height = 300
main_win.geometry(f'{width}x{height}')
cav = Canvas(main_win, width=width, height=height, bg='blue')
cav.pack()
main_win.mainloop()
可以看到,生成了一张和主窗口一样尺寸的蓝色画布。
cursor
指定 鼠标的显示样式,当鼠标落在画布区域时。样式的值是arrow’, ‘watch’, ‘cross’.
relief
指定边框样式,默认样式为’flat’,样式的种类有:‘flat’, ‘groove’, ‘raised’, ‘ridge’, ‘solid’, ‘sunken’
canvas的属性非常多哈,不可能一一列举,下面还是介绍一下实例,来辅助熟悉canvas的使用。
画直线
create_line(*args, **kw)
args参数为x1,y1,…,xn,yn 坐标值
kw参数为其他属性,fill用来填充直线的颜色;outline 为外围轮廓的颜色 ,width为线宽
cav = Canvas(main_win, width=width, height=height, bg='white')
cav.pack()
cav.create_line(0,height/2,width/4,height/4,width/2,height/2,(width/4)*3,(height/4)*3,width,height/2,fill='#ff0000')
cav.create_line(0,height/2,width,height/2,fill='#ff0000')
画圆(椭圆)
create_oval(*args, **kw):
args参数 为x1,y1,x2,y2;坐标(x1,y1),(x2,y2)指定一个矩形(正方形)的左上角和右下角。圆或椭圆就在这个矩形内部。
kw参数为其他属性,如fill,outline,width
cav = Canvas(main_win, width=width, height=height, bg='white')
cav.pack()
cav.create_oval(75,75, 225,225, fill='blue', outline='yellow',width=5)
cav.create_rectangle(75,75, 225,225,outline='red')
cav = Canvas(main_win, width=width, height=height, bg='white')
cav.pack()
cav.create_oval(55,85, 225,200, fill='blue', outline='yellow',width=5)
画矩形
create_rectangle(*args, **kw)
args参数 为x1,y1,x2,y2;坐标(x1,y1),(x2,y2)指定一个矩形(正方形)的左上角和右下角。
kw参数为其他属性,如fill,outline,width
cav = Canvas(main_win, width=width, height=height, bg='white')
cav.pack()
cav.create_rectangle(75,75, 225,225,outline='red')
cav.create_rectangle(85,85, 215,215,outline='blue', width=5)
cav.create_rectangle(95,95, 205,205,fill='purple')
画多边形
create_polygon( *args, **kw)
args参数为x1,y1,…,xn,yn 坐标值
kw参数为其他属性,fill用来设置直线的颜色;
使用游戏中的角色属性雷达图,来演示多边形的使用。
from math import (sin, cos, pi)
cav = Canvas(main_win, width=width, height=height, bg='white')
cav.pack()
# x,y,r,angle,direct
def set_point(x,y,r,angle=0,direct='n'):
if direct == 'n':
point = (x,y-r)
elif direct == 'en':
point = (x+r*sin(angle), y-r*cos(angle))
elif direct == 'es':
point = (x+r*sin(angle), y+r*cos(angle))
elif direct == 's':
point = (x,y+r)
elif direct == 'ws':
point = (x-r*sin(angle), y+r*cos(angle))
elif direct == 'wn':
point = (x-r*sin(angle), y-r*cos(angle))
return point
center_x=width/2
center_y=height/2
r = 100
radar_angle = pi/3
n_point = set_point(center_x, center_y, r, direct='n')
en_point = set_point(center_x, center_y, r, radar_angle, 'en')
es_point = set_point(center_x, center_y, r, radar_angle, 'es')
s_point = set_point(center_x, center_y, r, direct='s')
ws_point = set_point(center_x, center_y, r, radar_angle,'ws')
wn_point = set_point(center_x, center_y, r, radar_angle,'wn')
cav.create_polygon(*n_point, *en_point, *es_point, *s_point, *ws_point, *wn_point, fill='gray')
cav.create_text(*n_point, text='攻击力', fill='blue')
cav.create_text(*en_point, text ='防御力', fill='blue')
cav.create_text(*es_point, text='力量', fill='blue')
cav.create_text(*s_point, text='敏捷', fill='blue')
cav.create_text(*ws_point, text='智力', fill='blue')
cav.create_text(*wn_point, text='魔法值', fill='blue')
cav.create_line(*wn_point, *es_point, dash=(1,1))
cav.create_line(*n_point, *s_point, dash=(1,1))
cav.create_line(*en_point, *ws_point, dash=(1,1))
# 粉色表示角色A的属性
r = 50
n_point = set_point(center_x, center_y, r+30, direct='n')
en_point = set_point(center_x, center_y, r+6 , radar_angle, 'en')
es_point = set_point(center_x, center_y, r+20, radar_angle, 'es')
s_point = set_point(center_x, center_y, r , direct='s')
ws_point = set_point(center_x, center_y, r+30, radar_angle,'ws')
wn_point = set_point(center_x, center_y, r , radar_angle,'wn')
cav.create_polygon(*n_point, *en_point, *es_point, *s_point, *ws_point, *wn_point, fill='#FFC0CB')
# 红色表示角色B的属性
r = 70
n_point = set_point(center_x, center_y, r, direct='n')
en_point = set_point(center_x, center_y, r, radar_angle, 'en')
es_point = set_point(center_x, center_y, r, radar_angle, 'es')
s_point = set_point(center_x, center_y, r, direct='s')
ws_point = set_point(center_x, center_y, r+20,radar_angle,'ws')
wn_point = set_point(center_x, center_y, r,radar_angle,'wn')
cav.create_polygon(*n_point, *en_point, *es_point, *s_point, *ws_point, *wn_point, fill='', outline='red')
画弧线
create_arc(*args, **kw)
args参数为x1,y1,x2,y2 坐标值
kw参数为其他属性, start表示起始弧度,extent表示结束弧度。
根据初中的几何知识,圆弧是由射线绕它的端点旋转,在旋转过程中射线上的点会形成一条狐。
看着create_arc函数的参数,我们可能会想,画弧线,那得指定起点(端点),指定弧度,怎样设置呢?
cav = Canvas(main_win, width=width, height=height, bg='white')
cav.pack()
cav.create_line(0,height/2,width,height/2,fill='#ff0000')
cav.create_line(width/2,0,width/2,height,fill='#ff0000')
cav.create_arc(100, 150, 150, 200, start=0, extent=320)
cav.create_rectangle(100,150,150,200,outline='red') # 画一个矩形,方便描述
上面的示例代码中,(x1,y1)=(100,150),(x2,y2)=(150,200),刚好形成一个矩形,那么圆弧的起点(端点)就是矩形的中心点,半径为(x2-x1)/2,射线绕端点(中心点)逆时针从start弧度旋转到extent弧度。这就形成了下图所示的圆弧。
显示文字
create_text(*args, **kw)
args参数为x1,y1,x2,y2 坐标值
kw参数为其他属性,如fill,outline,width,font
在画多边形
小节中,其实已经使用过该函数。
cav = Canvas(main_win, width=width, height=height, bg='white')
cav.pack()
cav.create_text(100,100, text='渔道', fill='blue')
cav.create_text(100,150, text='python', fill='red', font=('Courier', 20, 'bold'))
显示图片
create_image(*args, **kw)
png = PhotoImage(file='qq.png')
width = png.width()
height = png.height()
main_win.geometry(f'{width}x{height}')
cav = Canvas(main_win, width=width, height=height, bg='blue')
cav.pack()
cav.create_image(0,0,anchor='nw', image=png)
到目前为止,介绍的都是静态的显示效果,如果想让画面动起来,应该怎么做呢?
canvas提供了这种机制,可以让图形"动"起来。
import time
canvas = Canvas(main_win,width=width,height=height)
canvas.pack()
arc = canvas.create_arc(10, 50, 50, 100, start=30, extent=320)
for x in range(0,60):
canvas.move(arc,5,0)
main_win.update()
time.sleep(0.05)
main_win.mainloop()
canvas的内容非常的多,本文先介绍到这里。