今天單獨講解一下使用python自帶的tkinter模塊,如何做出下圖這種倒計時的效果。
我們使用tkinter模塊裡的Canvas畫布組件來完成這個倒計時的制作。
拆解最終完成的圖形,可以看到,除了按鈕用來作為啟動倒計時,用來表示倒計時的圓形進度條可以拆解為下面四個組件:
1. 黃色的外圓框(一個填充為空白,邊框為黃色的圓)
2. 紅色的扇形(進度條的核心,隨著倒計時而改變扇形的角度)
3. 黃色的同心圓(用來遮住扇形的內部,顯示出環繞進度條的效果)
4. 中間的文字(每秒倒計時,隨著扇形一起變化)
所以,其實並不難,我們來分別實現:
Canvas繪制圓形的函數是create_oval。所以繪制黃色的外圓框,和裡面黃色的小同心圓,都可以使用這個函數。具體方法是:
# 繪制黃色的外圓框
cv.create_oval(100,50,350,300,outline='yellow')
# 繪制黃色的小同心圓
cv.create_oval(150,100,300,250,fill='yellow',outline='yellow')
參數也比較簡單,前面四個數字分別代表了這個圓所占的正方形的左上角(x1和y1)和右下角(x2和y2)的坐標。當然這個正方形只是表示位置,並不會出現正方形的邊框或內容。
後面跟著的fill表示填充的顏色,如果不寫這個參數,就表示是一個空心的圓。outline表示外邊框的顏色,我們這裡都使用了黃色yellow。此外還有其他參數,比如width,可以表示外邊框的厚度,默認是1,我們這裡就沒有特意指定了。
接著繪制扇形。Canvas繪制扇形(弧形)的函數是create_arc。比如下面這條代碼就畫了上面例子中的一個四分之三圓形面積的扇形。
cv.create_arc(100,50,350,300,start=90,extent=270,fill="red",outline='yellow')
前面四個數字和繪制圓形的一樣,表示扇形所占正方形位置的左上角和右下角的坐標。fill和outline的參數也和圓形一樣,表示填充的顏色和外邊框的顏色。比較重要的參數是start和extent。
start參數表示扇形的起始角度,extent表示逆時針開始,繪制到多少角度。所以,這裡start=90,extent=270,就表示弧形的一邊是垂直的(90度起始角度),另一邊是向右水平的(逆時針旋轉270度)
而最後的文字(數字)可以使用Canvas的create_text函數:
cv.create_text(225,175,text='90',font =('微軟雅黑',64,'bold'),fill='red')
代碼中前面兩個數字表示文字中心的橫縱坐標,這也方便了我們,不管文字內容如何變化,可以始終居中。參數text表示顯示的內容,fill表示文字的顏色,font則表示文字的字體、大小、粗細等屬性。
組件就這麼多,實現的原理也很簡單:
雖然很簡單,但是其實這裡面也有幾個小坑:
from tkinter import *
import tkinter.messagebox as tm
count=90
angle=360
def countdown():
global angle,count,cv_arc
btn['state']=DISABLED
if angle==360:
angle -= 4
else:
cv.delete(cv_arc)
cv_arc=cv.create_arc(100,50,350,300,start=90,extent=angle,fill="red",outline='yellow')
angle -= 4
count-=1
cv.create_oval(150,100,300,250,fill='yellow',outline='yellow')
cv.create_text(225,175,text=count,font =('微軟雅黑',64,'bold'),fill='red')
if count==0:
tm.showinfo(message='倒計時結束!')
angle = 360
cv.delete(cv_arc)
cv_arc=cv.create_oval(100,50,350,300,fill='red',outline='yellow')
count=90
cv.create_oval(150,100,300,250,fill='yellow',outline='yellow')
cv.create_text(225,175,text=count,font =('微軟雅黑',64,'bold'),fill='red')
btn['state']=NORMAL
else:
root.after(1000,countdown)
root = Tk()
root.geometry('450x450')
root.resizable(0,0)
root.title('倒計時')
cv = Canvas(root,width=450,height=450,bg='white')
btn = Button(root,text='開始',width=5,command=countdown)
cv_btn = cv.create_window(225,350,window=btn)
cv.create_oval(100,50,350,300,outline='yellow')
cv_arc=cv.create_oval(100,50,350,300,fill='red',outline='yellow')
cv.create_oval(150,100,300,250,fill='yellow',outline='yellow')
cv.create_text(225,175,text=90,font =('微軟雅黑',64,'bold'),fill='red')
cv.pack()
root.mainloop()
當然,倒計時90秒只是一個例子,隨你願意,可以倒計時任意時間。但要注意的是,每一秒扇形的角度變化也要隨著倒計時數字的不同而調整。比如倒計時90秒時,每秒鐘就減少360/90=4度,如果倒計時60秒,則每秒鐘減少360/60=6度,倒計時120秒則是360/120=3度,以此類推。
當然,顏色和位置、大小都可以變化(問哥也覺得大盤的番茄炒蛋有點嚇人,但是主旋律,你懂得:D),只要注意前後順序,不要被新繪制的扇形擋住就好。
最後,大家也可以思考一下,如果想要倒計時的數字和外面的扇形並不同時變化,該如何實現。就是類似下面這種效果,扇形的變化更加平滑:
其實並不難,只要在現有的代碼上做一個小變化即可,大家開動腦筋思考一下吧。:D