Python可以這樣玩(9):Canvas繪圖功能


下圖是一個繪圖功能的測試,接下來的課程我們要用 Python Canvas 來達成這樣的功能。




如同前面的元件一樣,Canvas 是一個畫布元件,為 Tkinter 提供了繪圖功能,其提供的圖形元件包括 線形、圓形、圖片、甚至其他控制項。Canvas 控制項為繪製圖形圖表、編輯圖形、自訂控制項提供了可能。

為了讓我們的DEMO程式多一點趣味,並且打一下個人廣告,我就先把大頭貼放上去,並且做一些說明,用此當成程式的框架。

繪製圖片

使用 create_image(x0, x0, options ...) 用來在 canvas 上繪製圖片,該方法不能直接接受圖片路徑等作為參數,而是接受一個 PhotoImage 物件作為圖片參數。PhotoImage 類用於讀取圖片,但其只能讀取 GIF PGM/PPM 格式的圖片。anchor 屬性來改變圖片繪製的對齊方式,anchor = NW 即為指定該點座標為所繪圖片的左上角,程式碼如下:
from tkinter import *
root = Tk()
root.title('我的繪圖功能')
root.geometry('600x400')

canvas_width = 600
canvas_height = 300
cvs = Canvas(root,
             width=canvas_width,
             height=canvas_height,
             bg="white")
cvs.pack()

img = PhotoImage(file="myphoto.gif")
cvs.create_image(10,10, anchor=NW, image=img)

mainloop()




繪製文字

接下來我們將說明如何在 canvas 上繪製文字,我們將直接接續上面的例子以作為新的範例。create_text() 方法用來在 canvas 上繪製文字,該方法的頭兩個參數表示所要繪製的文字的座標,預設情況下,文字將以此座標為中心進行繪製。程式碼如下:

from tkinter import *
root = Tk()
root.title('我的繪圖功能')
root.geometry('600x400')

canvas_width = 600
canvas_height = 300
cvs = Canvas(root,
             width=canvas_width,
             height=canvas_height,
             bg="white")
cvs.pack()

img = PhotoImage(file="myphoto.gif")
cvs.create_image(10,10, anchor=NW, image=img)
cvs.create_text(10, canvas_height/2, anchor=NW, text="作者: Andrew Wang")

mainloop()

結果如下:




繪製直線 Line

在第一個例子裡,我們將演示如何畫一條直線。create_line(coords, options) 方法用來繪製一條直線,coords 為以整數表示的四個座標參數: x1, y1, x2, y2 ,這表示所要繪製的直線連接了 (x1, y1) (x2, y2) 這兩個點。除座標外, 該方法還接受其他可選的 options 參數,在下面的例子裡我們用 options 參數指定顏色為黑色。

因為是第一個例子,所以我們儘量做了簡化:創建一個 canvas 物件然後在其上繪製一條水準直線,這條直線將 canvas 分割為上下兩部分。

在傳入座標參數時,y = int(canvas_height / 2) 這種強制轉換整形的運算式是沒有必要的,因為 create_line() 方法也接受 float 類型作為座標參數,float 座標數值將被自動轉為整數。直接加入下面的程式碼:

y = int(canvas_height / 2)
cvs.create_line(0, y, canvas_width, y, fill="red")


執行結果如下:




繪製矩形、橢圓與扇形

矩形很容易,只要告知左上與右下的座標,再加上位置(一般使用左上NW的點)即可,橢圓oval與矩形的方式也相同,扇形也是給左上右下兩點,再給予起始角度與展開角度,零度在最右邊的點,然後逆時鐘展開,如下:
x1, y1, x2, y2=140, 10, 590, 290
cvs.create_rectangle(x1, y1, x2, y2,fill='yellow')
cvs.create_oval(x1, y1, x2, y2,fill='green')
cvs.create_arc(x1+90, y1+20, x2-90, y2-20,
start=30,extent=270,fill='blue')





繪製多邊形

如果要繪製一個多邊形,可以使用 create_polygon(x0, y0, x1, y1, x2, y2, ...)方法, 至少要傳入三個點的座標才可以繪製一個多邊形。下例用該方法繪製了一個三角形(最後一點會自動與第一點連接)

points = [10,180,150,200,100,290]
cvs.create_polygon(points, outline='black',fill='red', width=3)


繪製Bitmap

create_bitmap() 方法用來繪製 bitmap。以下 bitmap 在所有平臺上都可用:
error”“gray75”“gray50”“gray25”“gray12”“hourglass”“info”“questhead”“question”“warning”(這些都是內定值),下例將這些 bitmap 全部都繪製在另一個 canvas 上:

bitmaps = ["error", "gray75", "gray50", "gray25", "gray12",
"hourglass","info", "questhead", "question", "warning"]
nsteps = len(bitmaps)
step_x = int(canvas_width / nsteps)

for i in range(nsteps):
   cvs2.create_bitmap((i+1)*step_x - step_x/2,20, bitmap=bitmaps[i])

我們先計算出總各有幾個 bitmap,然後再計算將這些圖示平均分布在 canvas 上的寬度,最後決定出座標。

執行畫面如下:

移動繪圖物件

前面所有用 creat_xxx 狀造出來的圖形都是一個物件,所以我們可以在繪圖板上面移動某個物件,寫一個簡單的按鈕將繪圖物件向右邊移動,完整程式碼如下,新增程式碼為紅色文字:

from tkinter import *
root = Tk()
root.title('我的繪圖功能')
root.geometry('600x400')

canvas_width = 600
canvas_height = 300
cvs = Canvas(root, width=canvas_width, height=canvas_height,
 bg="white")
cvs.pack()

img = PhotoImage(file="myphoto.gif")
cvs.create_image(10,10, anchor=NW, image=img)
cvs.create_text(10, canvas_height/2, anchor=NW,
text="作者: Andrew Wang")
y = canvas_height / 2
cvs.create_line(0, y, canvas_width, y, fill="red")

x1, y1, x2, y2=140, 10, 590, 290
cvs.create_rectangle(x1, y1, x2, y2,fill='yellow')
cvs.create_oval(x1, y1, x2, y2,fill='green')
cvs.create_arc(x1+90, y1+20, x2-90, y2-20,start=30,extent=270,fill='blue')

points = [10,180,150,200,100,290]
obj = cvs.create_polygon(points, outline='black',fill='red', width=3)

cvs2 = Canvas(root, width=canvas_width, height=40, bg="orange")
cvs2.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(nsteps):
   cvs2.create_bitmap((i+1)*step_x - step_x/2,20, bitmap=bitmaps[i])

def move_right():
    cvs.move(obj, 2, 0)
   
button = Button(root, text='向右移動', command=move_right).pack()

mainloop()

我們要移動多邊形物件,這是我們最後一個建立的物件,它會在最上方,為此我們需要在建立此物件的時候給定一個名稱(obj),後面我們才能抓得到此物件。

當按下按鈕,Canvas move()方法中傳入此物件名稱,移動 x, y 軸的距離即可,結果如下圖:


程式寫作

一、 製作四個按鈕,可以上下左右移動一個圖像物件




二、 繪製一個圍棋棋盤




三、 動畫製作,讓圖片自動在面上由左而右移動




必須確認程式可以執行無誤

留言

這個網誌中的熱門文章

Python可以這樣玩(16):共陰/共陽七段顯示器

Python可以這樣玩(15):蜂鳴器與音樂

Python可以這樣玩(13):外部LED控制