[Day20] Tkinter 桌面應用程式專案 I


前言

在前面的課程中我們主要都是透過 CLI(Command Line Interface)指令碼去操作程式。然而對於一般使用者來說 CLI 不但有恐懼感和難以親近的感覺外,更需要額外學習指令,以上種種原因讓 CLI 對於使用者來說相對有距離感。而圖形化使用者介面(GUI)的直覺化設計,讓使用者可以更容易操作電腦系統。所以目前的主流作業系統都是以圖形化使用者介面(GUI)為主要操作介面。其中,桌面應用程式(Desktop Application)是使用者常使用的應用程式圖形化使用者介面(GUI)。

透過 GUI 可以讓一般使用者透過比較直覺的方式來和程式互動(畢竟要讓一般的使用者使用 Command Line 來操作程式還是挺難的),也可以讓整個使用者行為更為簡便。許多程式語言都有提供 GUI 的函式庫,讓開發者可以透過常見的元件,例如:按鈕(Button)、文字方塊、下拉式選單等方式來設計整個應用程式。在這裡,我們將使用 Python 內建的 Tkinter 模組來學習如何建立 GUI 桌面應用程式。

Tkinter 函式庫簡介

基本設計流程

撰寫 Tkinter GUI 程式主要會有以下三個步驟:

  1. 建立主視窗(設定視窗大小、位置和視窗名稱)
  2. 將元件(如:按鈕、文字方塊、選單等)放入視窗中
  3. 實作事件處理函式,當作使用者互動時的事件處理器(event handler)。例如:當使用者點擊某個按鈕時要觸發什麼行為。

對於一個有使用者介面的應用程式來說不外乎三件事情:UI Component 元件設計(介面上有哪些元素),Layout 排版(如何排版畫面上的元素),Event Handler 事件處理(當使用者觸發了事件後要做什麼事)

使用 tkinter 模組

若是使用 repl.it 線上編輯器的話,記得在點選 new repl 跳出提示框時選擇使用 tkinter 的選項,才能在點選 run 運行程式時在瀏覽器顯示我們的桌面應用程式成果。若是使用 VS Code + 終端機執行或是 Jupyter Notebook 就直接使用模組就可以了!

https://static.coderbridge.com/img/happycoder/ec7723b2f67b42b5adc8563e68207164

接著我們正式開始使用 tkinter 模組,一樣不免俗的我們先從最簡單的 Hello World 程式碼開始,在這邊我們要建立一個視窗(背景為白色),顯示 Hello World 文字:

# 引入 tkinter 模組,始用別名 tk 代表 tkinter,可以少打字
import tkinter as tk

# 建立主視窗,建立 Tk 物件實例
window = tk.Tk()

# 設定視窗標題
window.title('Hello World')
# 設定視窗大小 800x600
window.geometry('800x600')
# 設定背景顏色為白色
window.configure(background='white')

# 建立文字 Label 元件
text_label = tk.Label(window, text='Hello World')
# 設定字體和大小
text_label.config(font=('Arial', 44))
# 渲染元件
text_label.pack()

# 運行主程式,最後一定要運行 window.mainloop(),讓 window 不斷地重新整理
# 這部份可以想成是電影或是動畫,事實上是不斷翻頁,所以就是一個 while 迴圈的感覺 window.mainloop()

運行結果:

https://static.coderbridge.com/img/happycoder/d9b9245020704e60bdea0f98fc71f99a

恭喜你,已經完成第一個 Pytho 桌面應用程式了!

隨堂練習:Hello World 第一個桌面應用程式

請嘗試自己動手試試看把背景從白色變成黃色。

建立按鈕元件和監聽事件處理

接著以下是簡單的如何使用按鈕元件的範例程式,我們將建立一個按鈕元件,當點擊這個按鈕會 print('hello world') 顯示在終端機上:

# 引入 tkinter 模組,始用別名 tk 代表 tkinter,可以少打字
import tkinter as tk

# 建立主視窗,建立 Tk 物件實例
window = tk.Tk()

# 設定視窗標題
window.title('Hello World')
# 設定視窗大小寬x高 800x600
window.geometry('800x600')
# 設定背景顏色為白色
window.configure(background='white')

def click_me():
    # 於終端機印出文字
    print('hello world :)')

# 建立按鈕元件(第一個參數放入 window 代表要顯示在哪個區塊),顯示文字為 click me,command 是當點擊會觸發處理的函式
button = tk.Button(window, text='click me', command=click_me)
# 渲染按鈕元件
button.pack()

# 運行主程式,最後一定要運行 window.mainloop(),讓 window 不斷地重新整理
# 這部份可以想成是電影或是動畫,事實上是不斷翻頁,所以就是一個 while 迴圈的感覺 
window.mainloop()

建立和使用者互動方式:建立元件 -> 建立監聽的處理函式

隨堂練習:建立按鈕元件和監聽事件處理

試試看當使用者點擊時印出 click me 訊息。

更新屬性值

當我們想要達成點擊或是觸發事件後更改元件屬性的互動時,我們需要使用元件方法 configure(),例如以下是一個當點擊按鈕,會更改按鈕文字為 clicked!!! 的範例:

# 引入 tkinter 模組,始用別名 tk 代表 tkinter,可以少打字
import tkinter as tk

# 建立主視窗,建立 Tk 物件實例
window = tk.Tk()

# 設定視窗標題
window.title('Hello World')
# 設定視窗大小寬x高 800x600
window.geometry('800x600')
# 設定背景顏色為白色
window.configure(background='white')

def click_me():
    # 更新按鈕元件屬性值 text 為 clicked!!!
    button.configure(text='clicked!!!')

# 建立按鈕元件(第一個參數放入 window 代表要顯示在哪個區塊),顯示文字為 click me,command 是當點擊會觸發處理的函式
button = tk.Button(window, text='click me', command=click_me)
# 渲染按鈕元件
button.pack()

# 運行主程式,最後一定要運行 window.mainloop(),讓 window 不斷地重新整理
# 這部份可以想成是電影或是動畫,事實上是不斷翻頁,所以就是一個 while 迴圈的感覺 
window.mainloop()

隨堂練習:更新屬性值

當使用者點擊按鈕時,更改按鈕文字為 hit me!!

輸入框元件

接著我們要讓使用者可以輸入內容,所以我們要引入 Entry 元件。以下範例是讓使用者可以輸入內容,並顯示在畫面上。

# 引入 tkinter 模組,始用別名 tk 代表 tkinter,可以少打字
import tkinter as tk

# 建立主視窗,建立 Tk 物件實例
window = tk.Tk()

# 設定視窗標題
window.title('Hello World')
# 設定視窗大小寬x高 800x600
window.geometry('800x600')
# 設定背景顏色為白色
window.configure(background='white')

input_entry = tk.Entry(window)
input_entry.pack()

result_label = tk.Label(text='')
result_label.pack()

def click_me():
    # 取出 input 值
    input_text = input_entry.get()
    # 顯示在 Label 元件上
    result_label.configure(text=input_text)

# 建立按鈕元件(第一個參數放入 window 代表要顯示在哪個區塊),顯示文字為 click me,command 是當點擊會觸發處理的函式
button = tk.Button(window, text='click me', command=click_me)
# 渲染按鈕元件
button.pack()

# 運行主程式,最後一定要運行 window.mainloop(),讓 window 不斷地重新整理
# 這部份可以想成是電影或是動畫,事實上是不斷翻頁,所以就是一個 while 迴圈的感覺 
window.mainloop()

隨堂練習:輸入框元件練習

群組化與元素定位方式

若是同一區塊的元件我們會使用 Frame 來群組化元件。以下是簡單的如何使用按鈕元件並定位元素在視窗的位置的範例程式,建立主視窗後加入 3+1 個按鈕元件(上面三個下面一個),當點擊下方按鈕元件時,事件處理器會印出 hello world :)

# 引入 tkinter 模組,始用別名 tk 代表 tkinter,可以少打字
import tkinter as tk

# 建立主視窗和 Frame(把元件變成群組的容器)
window = tk.Tk()

# 將元件分為 top/bottom 兩群組並加入主視窗
top_frame = tk.Frame(window)
# 記得要使用 pack() 將元件畫出
top_frame.pack()
bottom_frame = tk.Frame(window)
# side 參數是定位元素位置
bottom_frame.pack(side=tk.BOTTOM)

# 建立事件處理函式(event handler),透過元件 command 參數存取
def echo_hello():
    print('hello world :)')

# 以下有三個按鈕元件
# 第一個按鈕
left_button = tk.Button(top_frame, text='Red', fg='red')
# 讓系統自動擺放元件,預設為由上而下(靠左)
left_button.pack(side=tk.LEFT)
# 第二個按鈕
middle_button = tk.Button(top_frame, text='Green', fg='green')
middle_button.pack(side=tk.LEFT)
# 第三個按鈕
right_button = tk.Button(top_frame, text='Blue', fg='blue')
right_button.pack(side=tk.LEFT)

# 以下為 bottom 群組
# bottom_button 綁定 echo_hello 事件處理,點擊該按鈕會印出 hello world :)
bottom_button = tk.Button(bottom_frame, text='Black', fg='black', command=echo_hello)
# 讓系統自動擺放元件(靠下方)
bottom_button.pack(side=tk.BOTTOM)

# 運行主程式
window.mainloop()

觀看成果:
https://static.coderbridge.com/img/kdchang/75cc6896898b4bcab306386195974c2f

總結

以上透過 Python 內建的 Tkinter 函式庫來建立一個簡單的 BMI 計算應用程式,讓同學感受一下 Python Tkinter 設計桌面應用程式的流程。

重新複習撰寫 Tkinter GUI 程式主要會有以下三個流程步驟:

  1. 建立主視窗(設定視窗大小、位置和視窗名稱)
  2. 將元件(如:按鈕、文字方塊、選單等)放入視窗中
  3. 實作事件處理函式,當作使用者互動時的事件處理器(event handler)。例如:當使用者點擊某個按鈕時要觸發什麼行為。

事實上,比起 CLI 來說 GUI 對於一般使用者在使用上確實是比較方便,若有興趣的同學也可以在專案作業規劃設計自己嘗試製作小遊戲或是更多有趣的不同應用。在官方文件中還有更多的元件和使用方式可以進一步探索,有興趣的學員可以參考官方文件說明,相信建立起基本觀念和開發流程步驟後學員可以很容易上手。當然,多動手練習是熟悉模組最快的方式!

參考文件

  1. tkinter — Python interface to Tcl/Tk