已獲原做者受權. 原系列地址: Python Tkinter
Canvas 爲 Tkinter 提供了繪圖功能. 其提供的圖形組件包括 線形, 圓形, 圖片, 甚至其餘控件. Canvas 控件爲繪製圖形圖表, 編輯圖形, 自定義控件提供了可能.
在第一個例子裏, 咱們將演示如何畫一條直線. create_line(coords, options)
方法用來繪製一條直線. coords
爲以整形表示的四個座標參數: x1, y1, x2, y2 . 這表示所要繪製的直線鏈接了 (x1, y1) 和 (x2, y2) 這兩個點. 除座標外, 該方法還接受其餘可選的 options
參數. 在下面的例子裏咱們用 options
參數指定顏色爲咱們網站的主題色: fill=#476042
.
由於是第一個例子, 因此咱們儘可能作了簡化: 建立一個 canvas 對象而後在其上繪製一條水平直線. 這條直線將 canvas 分割爲上下兩部分.
在傳入座標參數時, y = int(canvas_height / 2)
這種強制轉換整形的表達式是沒有必要的, 由於 create_line()
方法也接受 float 類型做爲座標參數, float 座標數值將被自動轉爲整形. 下面是第一個例子的代碼:php
from tkinter import * master = Tk() canvas_width = 80 canvas_height = 40 w = Canvas(master, width=canvas_width, height=canvas_height) w.pack() y = int(canvas_height / 2) w.create_line(0, y, canvas_width, y, fill="#476042") mainloop()
上述代碼在 Python3 下會有以下顯示:python
使用 create_rectangle(coords, options)
方法能夠繪製矩形. coords
參數依然表示兩個點的座標: 第一個點爲左上角座標, 第二個點爲右下角座標.編程
上面的窗口是由如下示例代碼生成的:canvas
from tkinter import * master = Tk() w = Canvas(master, width=200, height=100) w.pack() w.create_rectangle(50, 20, 150, 80, fill="#476042") w.create_rectangle(65, 35, 135, 65, fill="yellow") w.create_line(0, 0, 50, 20, fill="#476042", width=3) w.create_line(0, 100, 50, 80, fill="#476042", width=3) w.create_line(150,20, 200, 0, fill="#476042", width=3) w.create_line(150, 80, 200, 100, fill="#476042", width=3) mainloop()
下圖闡釋了上面兩個例子中 create_lines()
和 create_rectangle()
這兩個方法中, 用到的各個座標的含義:segmentfault
接下來咱們將說明如何在 canvas 上繪製文字. 咱們將直接修改上面的例子以做爲新的示例. create_text()
方法用來在 canvas 上繪製文字. 該方法的頭兩個參數表示所要繪製的文字的座標. 默認狀況下, 文字將以此座標爲中心進行繪製. 固然, 你也能夠複寫 anchor 屬性來改變文字繪製的對齊方式. 好比, anchor = NW
即爲指定該點座標爲所繪文字的左上角. text 屬性用以指定具體繪製在 canvas 上的文字.app
from tkinter import * canvas_width = 200 canvas_height = 100 colours = ("#476042", "yellow") box=[] for ratio in ( 0.2, 0.35 ): box.append( (canvas_width * ratio, canvas_height * ratio, canvas_width * (1 - ratio), canvas_height * (1 - ratio) ) ) master = Tk() w = Canvas(master, width=canvas_width, height=canvas_height) w.pack() for i in range(2): w.create_rectangle(box[i][0], box[i][1],box[i][2],box[i][3], fill=colours[i]) w.create_line(0, 0, # canvas 原點 box[0][0], box[0][1], # box[0] 的左上角座標 fill=colours[0], width=3) w.create_line(0, canvas_height, # canvas 的左下角座標 box[0][0], box[0][3], # box[0] 的左下角座標 fill=colours[0], width=3) w.create_line(box[0][2],box[0][1], # box[0] 的右上角座標 canvas_width, 0, # canvas 的右上角座標 fill=colours[0], width=3) w.create_line(box[0][2], box[0][3], # box[0] 的右下角座標 canvas_width, canvas_height, # canvas 的右下角座標 fill=colours[0], width=3) w.create_text(canvas_width / 2, canvas_height / 2, text="Python") mainloop()
雖然從代碼上來看, 咱們對以前的例子作了很大的改動, 但其所輸出的結果卻與前例相差不大, 僅僅在窗口的中間多了一個顯示 "Python" 字樣的方框:ide
本例中咱們改用變量存儲座標等參數, 這使得改動變的方便. 好比, 要將整個畫布的寬高設爲 90 * 190, 將 box[0] 的寬高比設爲 0.3, 在本例中將很容易作到, 但在以前的例子中卻要修改不少代碼.
本例運行後顯示以下窗口:oop
圖形 oval 是一個蛋形的曲線. 它形似橢圓, 但並非橢圓. 事實上, oval 這個概念沒有太明確的定義. 不少不一樣的曲線都被叫作 oval, 他們都有以下共同點:佈局
oval 這個詞源自拉丁語中的 ovum, 意爲 "蛋", 這很好的描述了它: 一條描述蛋形狀的曲線. 一個 oval 由兩條半徑不一樣的弧線組成. 下圖是一個特殊的 oval:網站
咱們可使用以下方法在 canvas 中建立一個 oval:
id = C.create_oval ( x0, y0, x1, y1, option, ... )
該方法的返回值爲所建立的 oval 對象在當前 canvas 上的 ID.
下面的代碼繪製了一個圓心在 (75, 75), 半徑爲 25 的正圓形:
from tkinter import * canvas_width = 190 canvas_height =150 master = Tk() w = Canvas(master, width=canvas_width, height=canvas_height) w.pack() w.create_oval(50,50,100,100) mainloop()
咱們能夠定義一個專門用來畫正圓形的方法:
def circle(canvas, x, y, r): id = canvas.create_oval(x-r, y-r, x+r, y+r) return id
咱們想要建立一個可在 canvas 上手動繪圖的應用, 但 canvas 並未提供畫單個點的方法. 咱們能夠經過繪製小的 oval 圖形來解決這個問題:
from tkinter import * canvas_width = 500 canvas_height = 150 def paint( event ): python_green = "#476042" x1, y1 = ( event.x - 1 ), ( event.y - 1 ) x2, y2 = ( event.x + 1 ), ( event.y + 1 ) w.create_oval( x1, y1, x2, y2, fill = python_green ) master = Tk() master.title( "Painting using Ovals" ) w = Canvas(master, width=canvas_width, height=canvas_height) w.pack(expand = YES, fill = BOTH) w.bind( "<B1-Motion>", paint ) message = Label( master, text = "Press and Drag the mouse to draw" ) message.pack( side = BOTTOM ) mainloop()
若是要繪製一個多邊形, 可使用 create_polygon(x0, y0, x1, y1, x2, y2, ...)
方法. 至少要傳入三個點的座標才能夠繪製一個多邊形.
下例用該方法繪製了一個三角形:
from tkinter import * canvas_width = 200 canvas_height =200 python_green = "#476042" master = Tk() w = Canvas(master, width=canvas_width, height=canvas_height) w.pack() points = [0,0,canvas_width,canvas_height/2, 0, canvas_height] w.create_polygon(points, outline=python_green, fill='yellow', width=3) mainloop()
運行後顯示爲以下窗口:
或許你在讀到這篇教程時聖誕節 立刻就到了/爲時尚早. 這裏咱們用 Python 和 Tkinter 作一些星星來裝點咱們的聖誕樹. 第一課星星幾乎沒有用到任何編程技巧:
from tkinter import * canvas_width = 200 canvas_height =200 python_green = "#476042" master = Tk() w = Canvas(master, width=canvas_width, height=canvas_height) w.pack() points = [100, 140, 110, 110, 140, 100, 110, 90, 100, 60, 90, 90, 60, 100, 90, 110] w.create_polygon(points, outline=python_green, fill='yellow', width=3) mainloop()
上例很是沒有技術含量. 若是咱們要改變星星的大小或胖瘦, 該怎麼辦? 上例中咱們只能從新指定全部點的座標, 這種作法乏味且易出錯. 所以, 咱們用了更多的編程技巧改造了上例. 首先, 咱們將星星的繪製放在一個方法體中, 並用星星的原點及兩個長度指定星星的具體形狀:
通過改造的代碼以下:
from tkinter import * canvas_width = 400 canvas_height =400 python_green = "#476042" def polygon_star(canvas, x,y,p,t, outline=python_green, fill='yellow', width = 1): points = [] for i in (1,-1): points.extend((x, y + i*p)) points.extend((x + i*t, y + i*t)) points.extend((x + i*p, y)) points.extend((x + i*t, y - i * t)) print(points) canvas.create_polygon(points, outline=outline, fill=fill, width=width) master = Tk() w = Canvas(master, width=canvas_width, height=canvas_height) w.pack() p = 50 t = 15 nsteps = 10 step_x = int(canvas_width / nsteps) step_y = int(canvas_height / nsteps) for i in range(1, nsteps): polygon_star(w,i*step_x,i*step_y,p,t,outline='red',fill='gold', width=3) polygon_star(w,i*step_x,canvas_height - i*step_y,p,t,outline='red',fill='gold', width=3) mainloop()
這個例子的運行結果更像一個X形. 很顯然, 用逐個指定座標點的方法繪製這個圖形將無比麻煩.
create_bitmap()
方法用來繪製 bitmap. 如下 bitmap 在全部平臺上均可用:
"error", "gray75", "gray50", "gray25", "gray12", "hourglass", "info", "questhead", "question", "warning"
下例將這些 bitmap 所有都繪製在一個 canvas 上:
from tkinter import * canvas_width = 300 canvas_height =80 master = Tk() canvas = Canvas(master, width=canvas_width, height=canvas_height) canvas.pack() bitmaps = ["error", "gray75", "gray50", "gray25", "gray12", "hourglass", "info", "questhead", "question", "warning"] nsteps = len(bitmaps) step_x = int(canvas_width / nsteps) for i in range(0, nsteps): canvas.create_bitmap((i+1)*step_x - step_x/2,50, bitmap=bitmaps[i]) mainloop()
結果以下:
使用 create_image(x0, x0, options ...)
用來在 canvas 上繪製圖片. 該方法不能直接接受圖片路徑等做爲參數, 而是接受一個 PhotoImage 對象做爲圖片參數. PhotoImage 類用於讀取圖片, 但其只能讀取 GIF 和 PGM/PPM 格式的圖片.
from tkinter import * canvas_width = 300 canvas_height =300 master = Tk() canvas = Canvas(master, width=canvas_width, height=canvas_height) canvas.pack() img = PhotoImage(file="rocks.ppm") canvas.create_image(20,20, anchor=NW, image=img) mainloop()
上面的代碼運行後輸出以下窗口:
編寫一個方法繪製一個棋盤: checkered(canvas, line_distance)
, 其中: "canvas" 即 Canvas 對象, 棋盤在其上繪製; "line_distance" 爲線間距.
代碼以下:
from tkinter import * def checkered(canvas, line_distance): # vertical lines at an interval of "line_distance" pixel for x in range(line_distance,canvas_width,line_distance): canvas.create_line(x, 0, x, canvas_height, fill="#476042") # horizontal lines at an interval of "line_distance" pixel for y in range(line_distance,canvas_height,line_distance): canvas.create_line(0, y, canvas_width, y, fill="#476042") master = Tk() canvas_width = 200 canvas_height = 100 w = Canvas(master, width=canvas_width, height=canvas_height) w.pack() checkered(w,10) mainloop()
上面的代碼運行後輸出以下窗口:
全系列:
[譯][Tkinter 教程01] 入門: Label 控件
[譯][Tkinter 教程02] Message 控件
[譯][Tkinter 教程03] Button 控件
[譯][Tkinter 教程04] Variable 類
[譯][Tinkter 教程05] Radiobutton 控件
[譯][Tkinter 教程06] Checkbox 控件
[譯][Tkinter 教程07] Entry 控件
[譯][Tkinter 教程08] Canvas 圖形繪製
[譯][Tkinter 教程09] Scale 控件
[譯][Tkinter 教程10] Text 控件
[譯][Tkinter 教程11] 對話框和消息框
[譯][Tkinter 教程12] 佈局管理 (Pack Place Grid)
[譯][Tkinter 教程13] Mastermind 遊戲
[譯][Tkinter 教程14] menu 菜單
[譯][Tkinter 教程15] event 事件綁定
譯者水平有限, 若有疏漏, 歡迎指正.
已得到原做者受權. 原文地址: Canvas Widgets