原文地址:http://effbot.org/tkinterbook/canvas.htm
canvas組件為tkinter提供了結(jié)構(gòu)化的圖形繪制功能。其功能強(qiáng)大翰蠢,既能夠繪制點線面等圖形,還能夠創(chuàng)建出圖形編輯器啰劲,甚至可以根據(jù)界面設(shè)計的需要實現(xiàn)出多種多樣的自定義組件梁沧。
canvas組件的使用場景
canvas是一個通用組件,主要用來顯示和編輯圖形呈枉。
canvas組件還被經(jīng)常用來實現(xiàn)自定義組件趁尼。例如,可以在一個canvas上繪制并更新矩形框來實現(xiàn)一個進(jìn)度條猖辫。
樣例
要在canvas上畫東西酥泞,需要使用create
方法來新增item。例如:
from Tkinter import *
master = Tk()
w = Canvas(master, width=200, height=100)
w.pack()
w.create_line(0, 0, 200, 100)
w.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))
w.create_rectangle(50, 25, 150, 75, fill="blue")
mainloop()
注意啃憎,在canvas中新增的item會一直存在到你刪除它芝囤。如果你想改變所畫的東西,可以通過coords
辛萍、itemconfig
悯姊、move
等方法來修改所繪制的item,也可以通過delete
方法將其刪除贩毕。例如:
i = w.create_line(xy, fill="red")
w.coords(i, new_xy) # change coordinates
w.itemconfig(i, fill="blue") # change color
w.delete(i) # remove
w.delete(ALL) # remove all items
一些概念
為了在canvas上顯示東西悯许,需要創(chuàng)建幾個canvas item,這些item會被存放在一個棧中辉阶。默認(rèn)情況下先壕,新繪制的item會被畫在所有已繪制item的最上邊,即覆蓋掉其他item谆甜。
canvas item
canvas組件支持以下標(biāo)準(zhǔn)item:
-
arc
(弧垃僚、弦、扇形) bitmap
-
image
(BitmapImage
實例或PhotoImage
實例) line
-
oval
(圓或橢圓) polygon
rectangle
text
window
弦规辱、扇形谆棺、橢圓、多邊形罕袋、矩形由邊和內(nèi)部區(qū)域組成改淑,邊和內(nèi)部區(qū)域均可以被設(shè)置為透明的碍岔。
window item被用來在canvas上放置其他tkinter組件,對于這些item溅固,canvas僅僅管理其幾何屬性付秕。
item類型可以使用C或C++進(jìn)行擴(kuò)展兰珍,通過Python包的形式供tkinter使用侍郭。
坐標(biāo)系統(tǒng)
canvas組件使用兩種坐標(biāo)系:window坐標(biāo)系和canvas坐標(biāo)系。windows坐標(biāo)系以窗口左上角作為原點(0, 0)掠河,而canvas坐標(biāo)系則會明確指明item在畫布上的位置亮元。通過滾動canvas,可以指明要在window上顯示canvas坐標(biāo)系上的哪一部分區(qū)域唠摹。
scrollregion
屬性被用來限制canvas的滾動操作爆捞,可以這樣對其進(jìn)行設(shè)置:
canvas.config(scrollregion=canvas.bbox(ALL))
通過canvasx
和canvasy
方法可以將window坐標(biāo)轉(zhuǎn)換為canvas坐標(biāo),代碼如下:
def callback(event):
canvas = event.widget
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
print canvas.find_closest(x, y)
item標(biāo)識符:句柄和標(biāo)簽
canvas組件提供了幾個標(biāo)識item的方法:
- item句柄(整數(shù))
- 標(biāo)簽
ALL
CURRENT
item句柄是個整數(shù)值勾拉,用來標(biāo)識canvas中的一個item煮甥。tkinter會為每個在canvas上新創(chuàng)建的item自動分配一個句柄。item句柄可以通過整數(shù)形式或字符串形式傳遞給canvas提供的各類方法藕赞。
標(biāo)簽是附屬于item的一個象征性名稱成肘。標(biāo)簽是原始字符串,但不能包含空格斧蜕。一個item可以沒有標(biāo)簽示辈,也可以擁有多個標(biāo)簽跳芳,且一個標(biāo)簽名可以用于多個item。標(biāo)簽被item所擁有,依附于item而存在蘑志。
要為一個item增加標(biāo)簽,可以使用itemconfig
方法設(shè)置item的tags
屬性或通過addtag_withtag
方法直接新增揽碘。item的tags
屬性可接受字符串或字符串元組作為入?yún)⑵只病4a如下:
item = canvas.create_line(0, 0, 100, 100, tags="uno")
canvas.itemconfig(item, tags=("one", "two"))
canvas.addtag_withtag("three", "one")
要獲取一個特定item的所有標(biāo)簽,可使用gettags
方法掀宋。要通過標(biāo)簽獲取相關(guān)item深纲,可使用find_withtag
方法。代碼如下:
>>> print canvas.gettags(item)
('one', 'two', 'three')
>>> print canvas.find_withtag("one")
(1,)
canvas組件提供了兩個預(yù)定義標(biāo)簽:
-
ALL
(或字符串"all"
)其匹配canvas中的所有item布朦。 -
CURRENT
(或字符串"current"
)其匹配鼠標(biāo)指針?biāo)赶虻膇tem囤萤。這可以在鼠標(biāo)事件的處理中來找到觸發(fā)事件的item。
打印
tkinter組件支持向PostScript打印機(jī)進(jìn)行輸出是趴。
性能問題
canvas組件實現(xiàn)了一個直接的毀掉重來型的顯示模式(straight-forward damage/repair display model涛舍,這..有啥官方翻譯不...)。任何對canvas的修改和如Expose
之類的外部事件都被認(rèn)為是對屏幕的破壞唆途。組件維護(hù)了一個dirty rectange
來記錄被破壞的區(qū)域富雅。
當(dāng)?shù)谝粋€破壞事件到來時掸驱,canvas注冊一個待機(jī)任務(wù)(通過after_idle
方法),該任務(wù)會在程序回到tkinter主循環(huán)時修復(fù)canvas没佑。此外也可以通過調(diào)用update_idletasks
來強(qiáng)制更新canvas毕贼。
在重繪canvas時,會先分配一個與dirty rectangle
尺寸一樣的像素圖(一塊內(nèi)存)蛤奢。之后遍歷canvas中的item并對其中與dirty rectangle
有重疊的item進(jìn)行重繪鬼癣。最后,這塊像素圖會被復(fù)制到顯示屏上啤贩,同時存放像素圖的內(nèi)存被釋放待秃,這個復(fù)制過程在現(xiàn)代計算機(jī)上會非常快痹屹。
由于canvas僅使用了一個dirty rectangle
章郁,因此可以通過強(qiáng)制更新來得到更好的性能。例如志衍,如果要同時改變畫布中不同的幾個區(qū)域暖庄,可以通過在改變后直接調(diào)用update_idletasks()
來分別進(jìn)行更新,以避免回到主循環(huán)進(jìn)行重繪的時候dirty rectangle
較大而不得不重繪大量其實并沒有被改變的item楼肪。
API參考手冊
略