tkinter 圖形化介面程式設計

Tk 是開放原始碼的圖形化介面開發工具,具備跨平台的特性,它使用 Tcl 表述語言,所以通常合稱 Tcl/Tk,能夠三行程式碼寫出一個時鐘視窗程式。Python 程式語言為了 Tk 設計一套 interface,命名為 Tkinter。Perl、Ruby、Haskell、Common Lisp、Ada 也都有自己的程式庫來進行 Tk 程式設計,可見 Tk 被廣泛使用。

Windows 和 macOS 版的 CPython 內附 Tcl/Tk 執行環境,加上大多 Linux 發行版都預裝好 Tcl/Tk,等於 Tkinter 模組是 Python 內建的圖形介面程式庫!在 Python 使用 Tkinter 開發的 Tk 視窗程式,幾乎能在所有作業系統的 Python 直譯器執行!

但 Tkinter 不太像標準程式庫,有些作業系統沒有 Tcl/Tk,這些作業系統的 CPython 不但沒有 Tcl/Tk,連 Tkinter 模組都沒內建進去。

無論如何,Tkinter 是 Python 官方預設的 GUI 模組,使用 Tkinter 設計圖形介面應用程式,依然是最容易發行給大家使用的!


基礎範例


Step 1: 先簡單產生一個應用程式視窗


插圖


Step 2: 接著設定視窗大小與標題


插圖


Step 3: 然後加入元件例如按鈕


插圖


Step 4: 最後設計按鈕的功能


插圖


Step 5: 一個視窗程式就設計出來了

以這視窗為基礎,再依樣畫葫蘆將:Canvas、Checkbutton、Entry、Frame、Label、LabelFrame、Listbox、Menu、Menubutton、Message、OptionMenu、PanedWindow、Radiobutton、Scale、Scrollbar、Spinbox、Text、Toplevel 等元件加進去,Tk 視窗程式設計就這樣而已,很簡單對吧!

這些元件不用全背下來,而是要學會看文件,邊查元件功能邊寫程式,或者用程式設計專用文字編輯器的語法提示功能,就能視為學完 Tk 程式設計了。


再探基礎範例


更方便快寫 Tk 程式

為了更快速撰寫 Tk 視窗程式,上一章節的程式碼可以改為:


將事件分開來寫

如果按鈕的動作很多行,寫在元件的建構參數裡面就不適合,所以建議將事件的動作,用函式分開來寫:


注意!事件(例如 command)接受的是「函式名稱」,後面並沒有 () 符號,所以不是「呼叫函式」。既然不是呼叫函式,而是傳函式物件的參考給事件,那寫給事件的函式想帶參數怎麼辦?要用 lambda 執行:


另外加入事件

每個元件,可用 bind() 將函式與事件繫結在一起,例如:


更多可繫結的事件:

<Button-1>按一下滑鼠左鍵
<Button-2>按一下滑鼠中鍵
<Button-3>按一下滑鼠右鍵
<Double-Button-1>雙擊滑鼠左鍵
<Double-Button-2>雙擊滑鼠中鍵
<Double-Button-3>雙擊滑鼠右鍵
<ButtonRelease-1>放開滑鼠左鍵
<ButtonRelease-2>放開滑鼠中鍵
<ButtonRelease-3>放開滑鼠右鍵
<Enter>滑鼠游標移進
<Leave>滑鼠游標移出
<Key>按下鍵盤(可用 callback 的 event 參數判斷哪個鍵)
<Shift_L>按下 Shift 鍵
<Control_L>按下 Ctrl 鍵
<Alt_L>按下 Alt 鍵
<Return>按下 Enter 鍵
<Cancel>按下 Esc 鍵
<F1> ~ <F12>按下 F1~F12 鍵
<Up> <Down> <Left> <Right>按下 ↑ ↓ ← → 鍵
<FocusIn>取得駐點
<FocusOut>失去駐點
<Configure>狀態變動

事後修改元件屬性

元件的屬性可用 config() 修改,例如 button.config(text='再亂按啊')


預設元件樣式

可以在 Tk() 物件用 option_add() 預設元件的樣式:


需要注意有大小寫之分,而且樣式屬性寫錯不會報錯,所以寫這程式時要馬上測試結果,才不會到後來找不到問題出在哪。


改用 ttk 元件

Tk 使用作業系統原生圖形,所以在不同作業系統會有不一樣的風貌。如果要保持一致的外觀,可用 ttk 元件。

由於 ttk 元件相容 Tk 元件,所以可以不修改程式,只要引進 ttk 模組取代 tk 模組,就改用 ttk 元件了:


插圖

會改為 ttk 的元件有:Button、Checkbutton、Entry、Frame、Label、LabelFrame、Menubutton、PanedWindow、Radiobutton、Scale、Scrollbar,此外還追加了 Combobox、Notebook、Progressbar、Separator、Sizegrip、Treeview。

如果想同時混用 tk 和 ttk 的元件,可以這樣寫:


視窗內元件的布局管理

Tkinter 提供三種在視窗內配置元件的機制:指定座標配置元件的 place()、指定方位配置元件的 pack()、劃分格子配置元件的 grid()


place

在基礎範例已經示範過 place(),所以就略過不再重複介紹了。

需要補充的是,只有 place() 可以指定元件的大小,其它是自動調整元件大小。

其它可用的參數:

anchor = N, E, S, W, NE, NW, SE, SW
bordermode = INSIDE | OUTSIDE
relheight = 0.0 ~ 1.0
relwidth = 0.0 ~ 1.0
relx = 0.0 ~ 1.0
rely = 0.0 ~ 1.0


pack


插圖

其它可用的參數:

expand = False | True
fill = NONE | X | Y | BOTH

不下參數的話,直接打 xxx.pack(),會位置置中,從上到下排列下去。


grid


插圖

其它可用的參數:

rowspan = 佔用格數
columnspan = 佔用格數
ipadx = 像素大小
ipady = 像素大小
padx = 像素大小
pady = 像素大小
sticky = '' | N | E | S | W | NE | NW | SE | SW


Tkinter 8.5 reference: a GUI for Python 導讀

不知道為什麼,Python 官方文件《Python interface to Tcl/Tk》寫得奇差無比,明明是 The Python Standard Library 文件,卻像 Tutorial 分門別類地教你認識這玩意兒,無法當辭典查找想要的資料。因此實際寫 Tk 圖形介面程式的話,我用《Tkinter 8.5 reference: a GUI for Python》邊查功能邊寫程式。


Widgets, pop-up dialogs

一覽各 Widgets 的 options 和 methods:

Button
Canvas
Checkbutton
Entry
Frame
Label
LabelFrame
Listbox
Menu
Menubutton
Message
OptionMenu
PanedWindow
Radiobutton
Scale
Scrollbar
Spinbox
Text
ttk.Button
ttk.Checkbutton
ttk.Combobox
ttk.Entry
ttk.Frame
ttk.Label
ttk.LabelFrame
ttk.Menubutton
ttk.Notebook
ttk.PanedWindow
ttk.Progressbar
ttk.Radiobutton
ttk.Scale
ttk.Scrollbar
ttk.Separator
ttk.Sizegrip
ttk.Treeview
Toplevel
messagebox
filedialog
colorchooser


Standard attributes

各 Widget 的 options 設定方式,不外乎這些:DimensionsThe coordinate systemColorsType fontsAnchorsRelief stylesBitmapsCursorsImagesGeometry stringsWindow namesCap and join stylesDash patternsMatching stipple patterns


Universal widget methods

Universal widget methods 整理了每個 Widget 都有的 methods。


Events

最後把事件的架構弄得更清楚點:Levels of bindingEvent sequencesEvent typesEvent modifiersKey namesWriting your handler: The Event classThe extra arguments trickVirtual events


應用範例集


Message

Label 適合顯示標題文字(單行),不適合顯示段落文字(多行),想顯示多行文字,應該用 Message。

Message 會自動斷行,因此通常得設定 width 決定每行文字的長度,否則你會發現它每個單字就斷行。

預設是置中靠左對齊,你可以用 anchor 改變位置。


插圖


呼叫另一個視窗

使用 os.system() 直接執行另一個 *.pyw 即可。

如果會跳出命令提示字元視窗,覺得礙眼的話,就改用 subprocess 模組的 call():


視覺化開發環境

Tk 有沒有視覺化工具?有個套件就是朝 RAD 設計,叫做 Pygubu…屁股噗。

由於 Tkinter 在架構上就很簡單,因此 Pygubu 的 GUI builder for tkinter 很容易上手,沒什麼複雜的項目,一看就懂。

但功能略嫌簡陋,像元件布局管理只能用 grid,無法對應 place,所以跟一般拖來拉去的 Visual Basic 和 C++ Builder 還是有落差,純粹就是看得到而已,卻像隔著透明玻璃一樣摸不到。

當然,畫好格子再把元件丟進去的 grid,確實是最理想的布局方式,既能自動調整布局、又能詳細微調每個位置,只是用起來沒那麼直覺而已,不熟 grid 的人會覺得難用。然而趁這個機會把 gird 的特性通盤掌握起來,對跨平台設計 GUI 其實是很有幫助的!


pygubu 套件

請安裝 pygubu 套件:

pip install pygubu

或前往 http://pypi.org/project/pygubu/ 下載原始碼,執行 python setup.py install 安裝。


執行 pygubu-designer.py

執行 [Python]\Scripts\pygubu-designer.py,即可開啟 Pygubu a GUI builder for tkinter 視覺化開發環境。

插圖


疑難

若執行 pygubu-designer.py 時,出現找不到 appdir 套件的錯誤訊息,安裝一下就好:

pip install appdir

或前往 http://pypi.org/project/appdirs/ 下載原始碼,執行 python setup.py install 安裝。


解除安裝

只能用 pip uninstall pygubu,無法用原始碼解除安裝。