tkinter-Canvas详解

Canvas 组件

Canvas(画布)组件为 Tkinter 的图形绘制提供了基础。Canvas 是一个高度灵活的组件,你可以用它绘制图形和图表,创建图形编辑器,并实现各种自定义的小部件。

--随心所欲绘制图像

Canvas(root, width=100, height=100) 单位像素

创建的对象一直保留,直到被修改才会覆盖

修改方法:

w.coords() 移动对象

w.itemcofig() 设置对象属性

w.delete() 删除对象

Canvas 组件支持对象

  • arc(弧形、弦或扇形)
  • bitmap(内建的位图文件或 XBM 格式的文件)
  • imageBitmapImage PhotoImage 的实例对象)
  • line(线)
  • oval(圆或椭圆形)
  • polygon(多边形)
  • rectangle(矩形)
  • text(文本)
  • window(组件)

其中,弦、扇形、椭圆形、圆形、多边形和矩形这些“封闭式”图形都是由轮廓线和填充颜色组成的,但都可以设置为透明(传入空字符串表示透明)。

常用创建方法:

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 组件提供几种方法让你指定画布对象:

  • Item handles (tkinter自动创建的唯一的画布对象的 ID--整型)
  • Tags  ( 类似于text Tags但 是仅为画布对象所拥有)
  • ALL  (Canvas中所有对象)
  • CURRENT  (鼠标指针下的画布对象(如果有的话))

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(<B1-Motion>, paint)

	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('<B3-Motion>', 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()
	

 EG: 画哆啦A梦(python Canvas) -- 历时4个小时画的,坐标好难找好

	''' 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()

 

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值