'''
Created on 2017年8月31日
@author: Nick
'''
#_*_coding:utf-8_*_
import tkinter as tk
from tkinter import *
from openpyxl.worksheet.properties import Outline
from _tkinter import create
'''
Tkinter教程之Canvas篇
'''
def eventPrint(event):
print('eventPrint!')
def printRect(event):
print('rectangle')
def printLine(event):
print('line')
# 提供可以用来进行绘图的Container,支持基本的几何元素,使用Canvas进行绘图时,所有的操作都是通过Canvas,不是通过它的元素
# 元素的表示可以使用handle或tag。
if __name__ == '__main__':
root = tk.Tk()
root.wm_title('Canvas')#设置窗体标题
root.wm_minsize(400, 400)#设置窗口最小化大小
root.wm_maxsize(2800, 2800)#设置窗口最大化大小
root.resizable(width=True, height=True)#设置窗口宽度不可变,高度可变
#2、创建一个Canvas,设置其背景色为白色,大小
cv = Canvas(root,bg = 'white',width = 100,height = 80)
cv.pack(side = TOP)
fram = Frame(root)
cv = Canvas(fram,bg = 'white',width = 800,height = 200)
#3、创建一个items,坐标为(10,10,110,110),并填充颜色为红色
cv.create_rectangle(10,10,110,110,fill = 'red')
#4、指定矩形的边框颜色为绿色
cv.create_rectangle(120,10,220,110,outline = 'green')
#5、指定边框的宽度
cv.create_rectangle(230,10,330,110,outline = 'black',width = 10)
#6、画虚线
# 使用属性dash,这个值只能为奇数
cv.create_rectangle(350,10,440,110,outline = 'black',width = 10,dash = 3)
#7、使用画刷填充
# 使用属性stipple
cv.create_rectangle(460,10,550,110,fill = 'red',outline = 'black',width = 10,dash = 3,stipple = 'gray12')
#8、修改item的坐标
# 使用Canvas的方法coords(原item,坐标元组)来重新设置item的坐标
# 重新设置rt的坐标(相当于移动一个item)
rt = cv.create_rectangle(570,10,660,110,fill = 'green',outline = 'black',width = 5,dash = 7,stipple = 'gray12')
cv.coords(rt,(680,10,770,110))
#9、创建item的tags
# 使用属性tags设置item的tag
# 使用Canvas的方法gettags获取指定item的tags
ta = cv.create_rectangle(10,120,110,220,fill = 'green',outline = 'black',width = 5,dash = 7,stipple = 'gray12',tags = 'r1')
print(cv.gettags(ta))
# 使用tags属性指定多个tags,即重新设置tags的属性,通过itemconfig(原item,属性字段)函数修改item属性值
cv.itemconfig(ta, tags = ('r2','r3','r4','r5'))
cv.gettags(ta)
print(cv.gettags(ta))
cv.pack(side = LEFT)
fram.pack(side = TOP)
fram_1 = Frame(root)
cv = Canvas(fram_1,bg = 'white',width = 800,height = 100)
#10、多个item使用同一个tag
cv.create_rectangle(10,10,110,110,fill = 'red',tags = ('r2','r3','r4','r5'))
cv.create_rectangle(120,10,220,110,fill = 'black',tags ='r1')
cv.create_rectangle(230,10,330,110,fill = 'green',tags ='r2')
#fid_withtag返回所有与tag绑定的item。,返回的是item的序号元组,item编号从1开始
cv.find_withtag('r2')
print(cv.find_withtag('r2'))
cv.pack(side = LEFT)
fram_1.pack(side = TOP)
#11、通过tag来访问item
# 得到了tag值也就得到了这个item,可以对这个item进行相关的设置。
fram_2 = Frame(root)
cv = Canvas(fram_2,bg = 'white',width = 800,height = 100)
cv.create_rectangle(10,10,80,80,fill = 'green',tags = ('r2','r3','r4','r5'))
cv.create_rectangle(90,10,160,80,fill = 'black',tags ='r1')
cv.create_rectangle(170,10,240,80,fill = 'red',tags ='r3')
# 将所有与tag('r3')绑定的item边框颜色设置为蓝色
for item in cv.find_withtag('r3'):
cv.itemconfig(item,outline = 'blue',width = 3)
cv.pack(side = LEFT)
fram_2.pack(side = TOP)
#13、向其它item添加tag
# 使用addtag_above、addtag_below来向上一个或下一个item添加tag
# 第一个参数是tag值,第二个参数数需要修改的item
fram_3 = Frame(root)
cv = Canvas(fram_3,bg = 'white',width = 800,height = 100)
tags_1 = cv.create_rectangle(10,10,80,80,fill = 'green',tags = ('r2','r3','r4','r5'))
tags_2 = cv.create_rectangle(90,10,160,80,fill = 'black',tags ='r1')
tags_3 = cv.create_rectangle(170,10,240,80,fill = 'red',tags ='r3')
# 向tags_2的上一个item(tags_3)添加rt1
cv.addtag_above('rt1', tags_2)
# 向tags_2的下一个item(tags_1)添加rt11
cv.addtag_below('rt11', 2)
#Canvas使用了stack的技术,新创建的item总是位于前一个创建的item之上,故调用above时,它会查找rt2上面的item为rt3,故rt3中添加了tag('r4'),同样add_below会查找下面的item。
for item in [tags_1,tags_2,tags_3]:
print(cv.gettags(item))
#14、返回其它item
# 使用find_above/find_below查找上一个或下一个item,并通过itemconfig()函数设置属性
cv.itemconfig(cv.find_above(tags_2),dash = 7,outline = 'blue',stipple = 'gray12')
cv.itemconfig(cv.find_below(tags_2),dash = 2,outline = 'black',stipple = 'gray12')
#Canvas使用了stack的技术,新创建的item总是位于前一个创建的item之上,故调用above时,它会查找rt2上面的item为rt3,故rt3中添加了tag('r4'),同样add_below会查找下面的item。
cv.pack(side = LEFT)
fram_3.pack(side = TOP)
#16、移动item
fram_4 = Frame(root)
cv = Canvas(fram_4,bg = 'white',width = 800,height = 100)
rt_1 = cv.create_rectangle(10,10,80,80,fill = 'green')
rt_2 = cv.create_rectangle(10,10,80,80,fill = 'green')
rt_3 = cv.create_rectangle(170,10,240,80,fill = 'red',tags = ('s1','s2','s3'))
# move可以指定x,y在相对偏移量,可以为负值
cv.move(rt_2,80,10)
cv.itemconfig(rt_2,fill = 'red')
#17、删除item
# delete删除给定的item
#使用id删除item
cv.delete(1)
#使用item名称删除item
cv.delete(rt_2)
#使用tag删除item
cv.delete('s1')
cv.pack(side = LEFT)
fram_4.pack(side = TOP)
#18、缩放item
# scale缩放item,计算公式:(coords - offset)*scale + offset
# scale的参数为(self,xoffset,yoffset,xscale,yscale),self可以是item的名称、id以及tag属性
fram_5 = Frame(root)
cv = Canvas(fram_5,bg = 'white',width = 800,height = 100)
sf = cv.create_rectangle(10,10,80,80,fill = 'green')
sf_1 = cv.create_rectangle(90,10,160,80,fill = 'green',tags = 'r1')
# 将y坐标放大为原来的2位,x坐标值不变
cv.scale(sf_1,0,0,1,2)
# 等价于
#cv.scale(2,0,0,1,2)
#cv.scale('r1',0,0,1,2)
#19、绑定item与event
ev_1 = cv.create_rectangle(170,10,240,80,fill = 'blue',tags = 'r1')
ev_2 = cv.create_rectangle(250,10,320,80,fill = 'black',tags = 'r2')
ev_3 = cv.create_rectangle(330,10,400,80,fill = 'red',tags = 'r3')
# 使用tag_bind来绑定item与事件,tag_bind(tagOrId, sequence, func, add)
# tagOrId可以是item名称、tag属性值,
# 只有点击到矩形的边框时才会触发事件,不使用add参数,默认就是向这个item添加一个处理函数,它不会替换原来的事件函数,例子结果:既响应左键又响应右键
# 只有点击到矩形的边框时才会触发事件
cv.tag_bind(ev_1, '<Button-1>', eventPrint)
cv.tag_bind('r2', '<Button-1>', eventPrint)
# 绑定item与左键事件
cv.tag_bind('r3','<Button-1>',printRect)
# 绑定item与右键事件
cv.tag_bind('r3','<Button-3>',printLine)
# 将事件与tag('r1')绑定后,创建新的item并指定已绑定事件的tag,新创建的item同样也与事件绑定,
ev_3 = cv.create_rectangle(330,10,400,80,fill = 'green',tags = 'r3')
cv.pack(side = LEFT)
fram_5.pack(side = TOP)
#20、绘制弧形
fram_6 = Frame(root)
cv = Canvas(fram_6,bg = 'white',width = 800,height = 50)
# 使用默认参数创建一个ARC,结果为90度,填充色为红色的扇形
cv.create_arc(10,10,80,80,fill = 'red')
#21、设置弧形的样式
# 使用三种样式,分别创建了扇形、弓形和弧形
d = {1:PIESLICE,2:CHORD,3:ARC}
for i in d:
cv.create_arc((10+80*i,10,80+80*i,80),style = d[i],fill = 'blue',outline = 'black',width = 5,dash = 7)
print(str(i) + d[i])
cv.pack(side = LEFT)
fram_6.pack(side = TOP)
fram_7 = Frame(root)
cv = Canvas(fram_7,bg = 'white',width = 800,height = 50)
#22、设置弧形的角度
# 使用三种样式,start指定起始角度;extent指定角度偏移
for i in d:
cv.create_arc((10+80*i,10,80+80*i,80),style = d[i],start = 30,extent = 30)
print(str(i) + d[i])
cv.pack(side = LEFT)
fram_7.pack(side = TOP)
#23、绘制位图
# 使用bitmap创建位图create_bitmap
# 使用bitmap属性来指定位图的名称,这个函数的第一个参数为一个点(x,y)指定位图存放位置的左上位置。
fram_8 = Frame(root)
cv = Canvas(fram_8,bg = 'white',width = 800,height = 100)
d = {1:'error',2:'info',3:'question',4:'hourglass'}
for i in d:
cv.create_bitmap((20*i,20*i),bitmap = d[i])
cv.pack(side = LEFT)
fram_8.pack(side = TOP)
root.mainloop()
#创建第二个根窗口
root_1 = tk.Tk()
root_1.wm_title('Canvas-one')#设置窗体标题
root_1.wm_minsize(400, 400)#设置窗口最小化大小
root_1.wm_maxsize(2800, 2800)#设置窗口最大化大小
root_1.resizable(width=True, height=True)#设置窗口宽度不可变,高度可变
#24、绘制GIF图像
# 创建gif图像create_image
# 先使用PhotoImage创建GIF图像,再将image属性来设置为新创建的img
fram_9 = Frame(root_1)
cv = Canvas(fram_9,bg = 'white',width = 800,height = 160)
img = PhotoImage(file = 'C:\\Users\\Nick\\Desktop\\1.gif')
cv.create_image((150,150),image = img)
cv.pack(side = LEFT)
fram_9.pack(side = TOP)
#25、绘制直线
# 创建带箭头的直线create_line
# 使用arrow属性来控制是否显示箭头
# 将直线的属性joinstyle分别设置为bevel/miter/round,测试其效果。
fram_10 = Frame(root_1)
cv = Canvas(fram_10,bg = 'white',width = 800,height = 160)
d = [(0,'none','bevel'),(1,'first','miter'),(2,'last','round'),(3,'both','round')]
for i in d:
cv.create_line(
(10,10 + i[0]*20,110,110+ i[0] * 20), # 设置直线的起始、终点
arrow = i[1], # 设置直线是否使用箭头
arrowshape = '40 40 10' # 设置箭头的形状(填充长度,箭头长度,箭头宽度
)
for i in d:
cv.create_line(
(130,10 + i[0]*30,220,110+ i[0] * 30), # 设置直线的起始、终点
arrow = i[1], # 设置直线是否使用箭头
arrowshape = '40 40 10', # 设置箭头的形状(填充长度,箭头长度,箭头宽度
joinstyle = i[2],
)
cv.pack(side = LEFT)
fram_10.pack(side = TOP)
#26、绘制椭圆
# 绘制椭圆,使用create_oval属性
fram_11 = Frame(root_1)
cv = Canvas(fram_11,bg = 'white',width = 800,height = 100)
# 创建一个长200,宽100的椭圆
cv.create_oval((10,10,210,110),fill = 'red')
cv.pack(side = LEFT)
fram_11.pack(side = TOP)
#27、创建多边形
# 创建多边形(三角形),使用create_polygon
fram_12 = Frame(root_1)
cv = Canvas(fram_12,bg = 'white',width = 800,height = 160)
# 创建一个直角三角形
# 指定三个点的坐标,三个点坐标必须满足三角形的定义。
cv.create_polygon((10,10,10,200,100,200),fill = 'blue')
# 创建四边形
cv.create_polygon((200,10,10,100,80,200,200,200),fill = 'blue')
cv.move(2,80,10)
cv.pack(side = LEFT)
fram_12.pack(side = TOP)
#28、修饰图形
# 创建多边形create_ploygon(三角形)
# smooth/splinesteps用来修改绘制的图形,不明白这两个参数还有其它什么作用。
fram_13 = Frame(root_1)
cv = Canvas(fram_13,bg = 'white',width = 800,height = 100)
# 创建一个直角三角形
cv.create_polygon((10,10,10,100,50,100),
smooth = True, # 平滑处理,但未找到控制此参数的项
splinesteps = 0, # 不明白是控制什么的???
)
cv.pack(side = LEFT)
fram_13.pack(side = TOP)
#29、绘制文字
fram_14 = Frame(root_1)
cv = Canvas(fram_14,bg = 'white',width = 800,height = 100)
# 创建一个文字对象,默认设置为居中对齐
# 使用anchor控制文字的位置,使用justify控制对齐方式
cv.create_text((10,10),text = 'Hello Text,居中',anchor = W,fill = 'blue')
cv.create_text((20,20),text = 'Hello Text,居左',anchor = W,fill = 'blue',justify = LEFT)
cv.create_text((30,30),text = 'Hello Text,居右',anchor = W,fill = 'blue',justify = RIGHT)
cv.pack(side = LEFT)
fram_14.pack(side = TOP)
#30、选中文字
# 使用anchor组件在Canvas上的位置,默认情况下为居中对齐,这样使用后其它的item将不能再使用button战胜的那块区域
fram_15 = Frame(root_1)
cv = Canvas(fram_15,bg = 'white',width = 800,height = 100)
# 创建一个文字对象,默认设置为居中对齐
# 使用anchor控制文字的位置,使用justify控制对齐方式
txt = cv.create_text((10,10),text = 'Hello Text',anchor = W)
# 设置文本的选中起始位置
cv.select_from(txt,2)
# 设置文本的选中结束位置
cv.select_to(txt,5)
cv.pack(side = LEFT)
fram_15.pack(side = TOP)
#31、创建组件
fram_16 = Frame(root_1)
cv = Canvas(fram_16,bg = 'white',width = 800,height = 100)
# 创建一个Button对象,默认设置为居中对齐
def printWindow():
print('window')
bt = Button(cv,text = 'ClickMe',command = printWindow)
#修改button在canvas上的对齐方式
cv.create_window((10,10),window = bt,anchor = W)
# 新创建的line对象与button有重叠
cv.create_line(10,10,20,20)
# 新创建的line不在button之上,即没有重叠
cv.create_line(30,30,100,100)
cv.pack(side = LEFT)
fram_16.pack(side = TOP)
root_1.mainloop()
Tkinter之Canvas篇
本文转载:CSDN博客