(轉)Python下使用Tkinter 製作圖形介面
1.tkinter
tkinter是Python下面向tk的圖形介面介面庫,可以方便地進行圖形介面設計和互動操作程式設計。tkinter的優點是簡單易用、與Python的結合度好。tkinter在Python 3.x下預設整合,不需要額外的安裝操作;不足之處為缺少合適的視覺化介面設計工具,需要通過程式碼來完成視窗設計和元素佈局。
本節採用的Python版本為3.x,如果想在python 2.x下使用tkinter,請通過apt-get進行安裝。需要注意的是,不同Python版本下的tkinter使用方式可能略有不同,建議採用Python3。
1.1.hello tkinter
首先介紹一個tkinter的基本例子,在IDLE中新建hello_tkinter.py,程式碼如下:
import tkinter as tk
# 建立tkinter視窗,設定視窗標題
top = tk.Tk()
top.title("Hello Test")
# 在視窗中建立標籤
labelHello = tk.Label(top, text = "Hello Tkinter!")
labelHello.pack()
# 執行並顯示視窗
top.mainloop()
然後是top的概念和pack操作的說明:略……(懶得寫啦哈哈)
表1 Label元件常用引數
引數 |
描述 |
height |
元件的高度(所佔行數) |
width |
元件的寬度(所佔字元個數) |
fg |
前景字型顏色 |
bg |
背景顏色 |
justify |
多行文字的對齊方式,可選引數為: LEFT、 CENTER、RIGHT |
padx |
文字左右兩側的空格數(預設為1) |
pady |
文字上下兩側的空格數(預設為1) |
在Shell下執行程式,就可以顯示出一個簡單的視窗了。
$ python3 hello_tkinter.py
Tkinter視窗效果
1.2.tkinter常用元件
雖然1.1中我們已經設計出了tkinter的基本視窗,但這時的視窗還過於簡陋,除了顯示資訊以外無法實現任何有效的功能。為了完成更多的使用者互動功能,我們還需要了解更多的tkinter介面元素,本節將介紹一些常用的tkinter元件。
1.2.1.按鈕元件
按鈕元件(Button)是tkinter最常用的圖形元件之一,通過Button可以方便地與使用者進行互動。下列程式碼實現了通過觸發按鈕事件(按下按鈕)來執行指定操作(改變標籤內容)的例子。
import tkinter as tk
def btnHelloClicked():
labelHello.config(text = "Hello Tkinter!")
top = tk.Tk()
top.title("Button Test")
labelHello = tk.Label(top, text = "Press the button...", height = 5, width = 20, fg = "blue")
labelHello.pack()
btn = tk.Button(top, text = "Hello", command = btnHelloClicked)
btn.pack()
top.mainloop()
程式碼中定義了btnHelloClicked()函式,並通過給Button的command屬性賦值來指定按鈕按下時執行btnHelloClicked()函式中的程式碼的功能。在該函式中,通過labelHello.config()更改了label的text引數,即更改了標籤的文字內容。
表2 Button元件基本引數
引數 |
描述 |
height |
元件的高度(所佔行數) |
width |
元件的寬度(所佔字元個數) |
fg |
前景字型顏色 |
bg |
背景顏色 |
activebackground |
按鈕按下時的背景顏色 |
activeforeground |
按鈕按下時的前景顏色 |
justify |
多行文字的對齊方式,可選引數為: LEFT、 CENTER、RIGHT |
padx |
文字左右兩側的空格數(預設為1) |
pady |
文字上下兩側的空格數(預設為1) |
Button元件效果
1.2.2.輸入框元件
輸入框(Entry)用來輸入單行內容,可以方便地向程式傳遞使用者引數。這裡通過一個轉換攝氏度和華氏度的小程式來演示該元件的使用。
import tkinter as tk
def btnHelloClicked():
cd = float(entryCd.get())
labelHello.config(text = "%.2f°C = %.2f°F" %(cd, cd*1.8+32))
top = tk.Tk()
top.title("Entry Test")
labelHello = tk.Label(top, text = "Convert °C to °F...", height = 5, width = 20, fg = "blue")
labelHello.pack()
entryCd = tk.Entry(top, text = "0")
entryCd.pack()
btnCal = tk.Button(top, text = "Calculate", command = btnHelloClicked)
btnCal.pack()
top.mainloop()
本例的程式碼從1.2.1中修改而來,並新建了一個Entry元件entryCd,text引數設定了輸入框的預設值為“0”。當按鈕按下後,通過entryCd.get()獲取輸入框中的文字內容,該內容為字串型別,需要通過float()函式轉換成數字,自後再進行換算並更新label顯示內容。
表3 Entry元件常用引數
引數 |
描述 |
height |
元件的高度(所佔行數) (無) |
width |
元件的寬度(所佔字元個數) |
fg |
前景字型顏色 |
bg |
背景顏色 |
show |
將Entry框中的文字替換為指定字元,用於輸入密碼等,如設定 show="*" |
state |
設定元件狀態,預設為normal,可設定為:disabled—禁用元件,readonly—只讀 |
執行效果
華氏攝氏溫度換算程式效果
1.2.3.單選、複選框
單選框(Radiobutton)和複選框(Checkbutton)分別用於實現選項的單選和複選功能。本例中的程式碼實現了通過單選框、複選框設定文字樣式的功能。
import tkinter as tk
def colorChecked():
labelHello.config(fg = color.get())
def typeChecked():
textType = typeBlod.get() + typeItalic.get()
if textType == 1:
labelHello.config(font = ("Arial", 12, "bold"))
elif textType == 2:
labelHello.config(font = ("Arial", 12, "italic"))
elif textType == 3:
labelHello.config(font = ("Arial", 12, "bold italic"))
else :
labelHello.config(font = ("Arial", 12))
top = tk.Tk()
top.title("Radio & Check Test")
labelHello = tk.Label(top, text = "Check the format of text.", height = 3, font=("Arial", 12))
labelHello.pack()
color = tk.StringVar()
tk.Radiobutton(top, text = "Red", variable = color, value = "red", command = colorChecked).pack(side = tk.LEFT)
tk.Radiobutton(top, text = "Blue", variable = color, value = "blue", command = colorChecked).pack(side = tk.LEFT)
tk.Radiobutton(top, text = "Green", variable = color, value = "green", command = colorChecked).pack(side = tk.LEFT)
typeBlod = tk.IntVar()
typeItalic = tk.IntVar()
tk.Checkbutton(top, text = "Blod", variable = typeBlod, onvalue = 1, offvalue = 0, command = typeChecked).pack(side = tk.LEFT)
tk.Checkbutton(top, text = "Italic", variable = typeItalic, onvalue = 2, offvalue = 0, command = typeChecked).pack(side = tk.LEFT)
top.mainloop()
在程式碼中,文字的顏色通過Radiobutton來選擇,同一時間只能選擇一個顏色。在三個Red、Blue和Green三個單選框中,定義了同樣的變數引數color,選擇不同的單選框會為該變數賦予不同的字串值,內容即為對應的顏色。
任何單選框被選中都會觸發colorChecked()函式,將標籤修改為對應單選框表示的顏色。
表4 Radiobutton元件常用引數
引數 |
描述 |
variable |
單選框索引變數,通過變數的值確定哪個單選框被選中。一組單選框使用同一個索引變數 |
value |
單選框選中時變數的值 |
command |
單選框選中時執行的命令(函式) |
文字的粗體、斜體樣式則由複選框實現,分別定義了typeBlod和typeItalic變數來表示文字是否為粗體和斜體。
當某個複選框的狀態改變時會觸發typeChecked()函式。該函式負責判斷當前那些複選框被選中,並將字型設定為對應的樣式。
表5 Checkbutton元件常用引數
引數 |
描述 |
variable |
複選框索引變數,通過變數的值確定哪些複選框被選中。每個複選框使用不同的變數,使複選框之間相互獨立 |
onvalue |
複選框選中(有效)時變數的值 |
offvalue |
複選框未選中(無效)時變數的值 |
command |
複選框選中時執行的命令(函式) |
執行效果
1.2.4.繪圖元件
繪圖元件(Canvas)可以在GUI中實現2D圖形的繪製,相當於畫圖板。元件內建了多種繪圖函式,可以通過簡單的2D座標繪製直線、矩形、圓形、多邊形等。本例程式碼演示了Canvas元件的繪圖功能,更多的繪圖函式可以查閱Canvas的參考頁面。
import tkinter as tk
def drawCircle(self, x, y, r, **kwargs):
return self.create_oval(x-r, y-r, x+r, y+r, **kwargs)
top = tk.Tk()
top.title("Canvas Test")
cvs = tk.Canvas(top, width = 600, height = 400)
cvs.pack()
cvs.create_line(50, 50, 50, 300)
cvs.create_line(100, 50, 200, 300, fill = "red", dash = (4, 4), arrow = tk.LAST)
cvs.create_rectangle(200, 50, 400, 200, fill = "blue")
cvs.create_oval(450, 50, 550, 200, fill = "green" )
drawCircle(cvs, 450, 300, 50, fill = "red")
cvs.create_polygon(200, 250, 350, 250, 350, 350, 220, 300, fill="yellow")
top.mainloop()
繪圖函式的引數都比較好理解,包括基本的座標和顏色、線型等附加引數。
直線(line),即線段,通過兩個端點定義。座標順序為x1、y1、x2、y2。
矩形(rectangle)通過對角線上的兩個點來定義。
需要注意的是Canvas中沒有畫圓函式,這裡通過繪製橢圓間接實現了繪製圓形的函式drawCircle()。橢圓(oval)是通過外切矩形的對角線兩點來定義的(別告訴我你不知道什麼是外切矩形……)。如下圖所示:
執行效果
1.2.5.訊息視窗
訊息視窗(messagebox)用於彈出提示框向用戶進行告警,或讓使用者選擇下一步如何操作。訊息框包括很多型別,常用的有info、warning、error、yeno、okcancel等,包含不同的圖示、按鈕以及彈出提示音。下面的程式碼演示了各訊息框的執行效果,大家可以自己一一嘗試。
import tkinter as tk
from tkinter import messagebox as msgbox
def btn1_clicked():
msgbox.showinfo("Info", "Showinfo test.")
def btn2_clicked():
msgbox.showwarning("Warning", "Showwarning test.")
def btn3_clicked():
msgbox.showerror("Error", "Showerror test.")
def btn4_clicked():
msgbox.askquestion("Question", "Askquestion test.")
def btn5_clicked():
msgbox.askokcancel("OkCancel", "Askokcancel test.")
def btn6_clicked():
msgbox.askyesno("YesNo", "Askyesno test.")
def btn7_clicked():
msgbox.askretrycancel("Retry", "Askretrycancel test.")
top = tk.Tk()
top.title("MsgBox Test")
btn1 = tk.Button(top, text = "showinfo", command = btn1_clicked)
btn1.pack(fill = tk.X)
btn2 = tk.Button(top, text = "showwarning", command = btn2_clicked)
btn2.pack(fill = tk.X)
btn3 = tk.Button(top, text = "showerror", command = btn3_clicked)
btn3.pack(fill = tk.X)
btn4 = tk.Button(top, text = "askquestion", command = btn4_clicked)
btn4.pack(fill = tk.X)
btn5 = tk.Button(top, text = "askokcancel", command = btn5_clicked)
btn5.pack(fill = tk.X)
btn6 = tk.Button(top, text = "askyesno", command = btn6_clicked)
btn6.pack(fill = tk.X)
btn7 = tk.Button(top, text = "askretrycancel", command = btn7_clicked)
btn7.pack(fill = tk.X)
top.mainloop()
執行效果