Python可以這樣玩(8):選擇類元件應用


如果任何內容都使用文字方塊來輸入,會變得很沒有效率,因為有些東西是可以讓使用者用選的方式來輸入,可以節省很多時間。選擇類元件包含了單選鈕(Radiobutton)、核取方塊(Checkbutton)、下拉式清單(Combobox)、以及清單方塊(Listbox)

讓我們一步一步示範這些元件的用法,整個程式的構想是,寫一個班級學生的輸入介面,可以讓老師輸入學生的姓名、性別、年級、班級、是否報到等資訊之後,插入到一個多行文字方塊之中,並提供刪除功能。

元件定位

首先我們來設計姓名輸入的文字框,要讓使用者清楚知道輸入姓名的位置,必須用到兩個元件,就是用 Label 以及 Entry,除此之外,之前的 pack()不能再用了,為了精準定位,我們使用 place() 精確的定出元件的位置:

import tkinter as tk

window = tk.Tk()
window.title('學生基本資料')
window.geometry('400x320')

labName = tk.Label(window, text = '學生姓名:', justify = tk.RIGHT, width = 50)
labName.place(x=10, y=10, width=100, height=20)

varName = tk.StringVar()
varName.set('')
entName = tk.Entry(window, width = 120, textvariable = varName)
entName.place(x=110, y=10, width=120, height=20)

window.mainloop()

請注意這裡已經把原本的 pack() 改成 place() 了,其中 x, y 是元件左上角對應視窗的座標。

接下來我們要輸入年級和班級,年級為一到三,班級為甲到戊,這兩個值是固定的,所以我們可以使用 combobox 來達成。

Combobox 下拉式選單

要使用 combobox,我們必須匯入 tkinter.ttk,年級的值按照規定要使用元組來儲存,程式碼如下:

import tkinter as tk
import tkinter.ttk as tt

window = tk.Tk()
window.title('學生基本資料')
window.geometry('400x320')

labName = tk.Label(window, text = '姓名:', justify=tk.RIGHT, width=50)
labName.place(x=10, y=10, width=100, height=20)

varName = tk.StringVar()
varName.set('')
entName = tk.Entry(window, width = 120, textvariable = varName)
entName.place(x=110, y=10, width=120, height=20)

labGrade = tk.Label(window, text = '年級:', justify=tk.RIGHT, width=50)
labGrade.place(x=10, y=40, width=100, height=20)

stdGrade = ('1','2','3')

comGrade = tt.Combobox(window, width=50, values=stdGrade)
comGrade.place(x=110, y=40, width=50, height=20)

window.mainloop()

執行結果如下:




用同樣的方式把每一個年級甲到戊班也放入 combobox 裡面,這種方式是兩個 combobox 各自獨立運作,有另外一種連動的 combobox 組,選取第一個之後才決定第二個的值,我們在此先不討論。

Radiobutton 單選鈕

單選鈕的特性就是,只能有一個選擇,性別就是標準的單選鈕,不是男生,就是女生。程式碼如下,紅色部分為相關部分:

import tkinter as tk
import tkinter.ttk as tt

window = tk.Tk()
window.title('學生基本資料')
window.geometry('400x320')

labName = tk.Label(window, text = '姓名:', justify=tk.RIGHT, width=50)
labName.place(x=10, y=10, width=100, height=20)

varName = tk.StringVar()
varName.set('')
entName = tk.Entry(window, width = 120, textvariable = varName)
entName.place(x=110, y=10, width=120, height=20)

labGrade = tk.Label(window, text = '年級:', justify=tk.RIGHT, width=50)
labGrade.place(x=10, y=40, width=100, height=20)

stdGrade = ('1','2','3')
comGrade = tt.Combobox(window, width=50, values=stdGrade)
comGrade.place(x=110, y=40, width=60, height=20)

labGrade = tk.Label(window, text = '班級:', justify=tk.RIGHT, width=50)
labGrade.place(x=190, y=40, width=100, height=20)

stdClass = ('','','','','')
comClass = tt.Combobox(window, width=50, values=stdClass)
comClass.place(x=300, y=40, width=60, height=20)

labSex = tk.Label(window, text = '性別:', justify=tk.RIGHT, width=50)
labSex.place(x=10, y=70, width=100, height=20)

varSex = tk.IntVar()
varSex.set(1)       # 預設值1=
radBoy = tk.Radiobutton(window, variable=varSex, value=1,text='男生')
radBoy.place(x=110, y=70, width=60, height=20)
radGirl = tk.Radiobutton(window, variable=varSex, value=0,text='女生')
radGirl.place(x=190, y=70, width=60, height=20)

window.mainloop()

Radiobutton 群組的觀念,同一個群組的 Radiobutton 只能有一個項目被選取,才能表現單選的特性,因此,在這個例子中性別就是一個群組,男生和女生則是群組裡面的兩個項目,那麼我們要如何區分是否是同一個群組呢?就是靠 variable=varSex 來表現,設定成相同變數名稱的,就是同一個群組。

接下來就是 value=1 代表男生,value=0 但表女生。執行結果如下圖 (點女生,男生就跳掉)




Checkbutton 核取方塊

核取方塊的表現與單選鈕完全不同,它是可以多重選擇的,所以可以各自獨立。我們就加一個 是否報到核取方塊,新增的程式碼如下:

signin = tk.IntVar()
signin.set(0)       # 預設值0=未報到
chkSignin = tk.Checkbutton(window, text='是否報到', variable=signin,
                        onvalue=1, offvalue=0)
chkSignin.place(x=100, y=100, width=100, height=20)

因為可以各自獨立,所以會有各自的 variable,透過 onvalue=1, onvalue=0 給予變數值。

Listbox 清單方塊

最後,我們加入一個新增按鈕、一個刪除按鈕、以及一個清單方塊,此範例我們先談新增功能,其他進階功能後面再補充,程式碼如下:

def addInfo():
    result = '姓名:' + entName.get()
    result += ';年級:' + comGrade.get()
    result += ';班級:' + comClass.get()
    result += ';性別:' + ('男生' if varSex.get() else '女生')
    result += ';報到:' + ('' if signin.get() else '')
    lstStudent.insert(0,result)
   
btnAdd = tk.Button(window, text='加入', width=40, command=addInfo)
btnAdd.place(x=150, y=100, width=100, height=20)

btnDel = tk.Button(window, text='刪除', width=40, command=addInfo)
btnDel.place(x=260, y=100, width=100, height=20)

lstStudent = tk.Listbox(window, width=380)
lstStudent.place(x=10, y=130, width=380, height=180)

請注意取值的方,前三個取元件的值,後兩個取變數的值。插入方式則是每次都插入第一行,執行結果如下:




到這裡為止,我們已經學會的大部分會用到的GUI元件,為了讓讀者不會覺得太枯燥,我們接下來來玩一下 tkinter 的繪圖功能。

留言

這個網誌中的熱門文章

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

Python可以這樣玩(11):數學繪圖

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