Tkinter之Canvas篇
https://blog.csdn.net/pengzhi5966885/article/details/77774820
Tkinter之Canvas篇
2017年09月01日 16:42:52 大個土豆 閱讀數:3440更多
'''
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()