2021年9月4日 星期六

Python 內建 GUI 模組 tkinter 測試 (九) : Radiobutton 元件

Tkinter 的 Radiobutton 元件是用來讓使用者單選 (多選一) 的選項元件. 

本系列之前的文章參考 :   

Radiobutton 元件為一種選項元件, 用來從多個選項中選擇一個項目, 只能單選. 其語法如下 :

Radiobutton(父容器, **參數列)   

此元件有 tk 與 ttk 版本.

參考 :


RadioButton 元件常用參數如下表 : 


 Radiobutton 常用參數 說明
 value 選項圓鈕之值, 用來區分不同之項目
 variable 與選項圓鈕綁定之變數類別物件名稱, 用來動態存取選項圓鈕之值
 text 選項圓鈕的項目顯示文字 (與 value 對應, 可與 value 不同)
 textvariable 綁定選項顯示文字的類別變數名稱
 command 當按鈕狀態改變時要執行的函式名稱
 width 元件寬度 (字元數)
 height 元件高度 (字元數, ttk 不支援)
 indicatoron  用按鈕形式顯示選項 (ttk 不支援)


其中要特別注意的是 variable 這參數, 其功能是用來將 Radiobutton 群組綁定到一個類別變數, 以便能動態存取 Radiobutoon 之值. 單選元件是由一群 Radiobutton 物件組成, 但要讓它們具有單選效果, 必須將各項目的 Radiobutton 之 variable 參數都設為相同名稱之類別變數, 然後用 value 參數區別不同的選項值, 整體結構如下 : 

var=StringVar()
var.set(初始值) 
rbtn1=tl.Radiobutton(win, variable=var, value=v1, text=t1)
rbtn2=tl.Radiobutton(win, variable=var, value=v2, text=t2)
rbtn3=tl.Radiobutton(win, variable=var, value=v3, text=t3)
.....

類別變數 var  視需要也可以是 IntVar(), DoubleVar() 或 BooleanVar(). 傳入類別變數 set() 方法的初始值可設為 value 參數的值 v1, v2, v3,... 看要用哪一個當作預設被選取之項目, 如果預設都不選取, 則只要傳入 v1, v2, v3... 以外的任何值即可. 

例如 : 


測試 1 : 單選圓鈕 tk 版 [看原始碼]

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as msgbox

def show_selection():
    msgbox.showinfo("info", "性別: " + gender.get())

win=tk.Tk()                                                      
win.title("tkinter GUI 測試") 
gender=tk.StringVar()               # 與單選圓鈕綁定的類別變數
gender.set("M")                         # 設定初始值
tk.Label(text="性別 : ", width=30, bg="cyan").pack()
tk.Radiobutton(win, text="男",
               variable=gender,    
               value="M",
               command=show_selection).pack()     # 選項 1
tk.Radiobutton(win, text="女",
               variable=gender,   
               value="F",
               command=show_selection).pack()     # 選項 2
win.mainloop()

此例為二選一的單選圓鈕, 利用相同的 variable 參數值 (=gender) 將這兩個圓鈕組成一個群組, 其值與名為 gender 的類別變數綁定在一起, 亦即可用 gender.set() 設定哪一個圓鈕被選取, 或呼叫 gender.get() 取得目前被選取的圓鈕之值. 另外 command 則可指定點選選項時要執行的函式名稱. 注意, 建立單選圓鈕群組後必須呼叫與其綁定的類別變數之 set() 方法設定初始值, 否則預設每個選項會被選取, 若要預設都不選取, 則可在呼叫 set() 時傳入一個所有選項的 value 以外之值即可, 結果如下 : 




可見 Radiobutton 的 text 參數負責顯示, 而 value 設定每個項目之值, 呼叫類別變數的 get() 方法傳回的是選項的 value, 不是 text. 

下面範例是上例的 ttk 版 : 


測試 2 : 單選圓鈕 ttk 版 [看原始碼]

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as msgbox

def show_selection():
    msgbox.showinfo("info", "性別: " + gender.get())

win=tk.Tk()                                                      
win.title("tkinter GUI 測試") 
gender=tk.StringVar()
gender.set("M")
ttk.Label(text="性別 : ", width=30, background="cyan").pack()
ttk.Radiobutton(win, text="男",
               variable=gender,
               value="M",
               command=show_selection).pack()
ttk.Radiobutton(win, text="女",
               variable=gender,
               value="F",
               command=show_selection).pack()
win.mainloop()

結果如下 : 




上面的範例的選項數目較少, 所以一個一個建立 Radiobutton 物件還 OK, 但如果選項較多時, 程式碼就會變得很冗長, 這時可將選項的值 (value 參數值) 與顯示文字 (text 參數值) 放在字典中, 然後使用 for 迴圈來建立 Radiobutton 元件, 例如 : 


測試 3 : 用字典搭配迴圈建立 Radiobutton 物件 [看原始碼]

import tkinter as tk
from tkinter import ttk

def show_selection():
    label_result["text"]="選擇結果: " + fruit.get()

win=tk.Tk()                                                      
win.title("tkinter GUI 測試") 
fruit=tk.StringVar()      # 綁定 Radiobutton 群組的類別變數
fruit.set("none")           # 設定初始值 (預設都不選)
tk.Label(text="請選擇最喜歡的水果 : ", width=30, bg="cyan").pack()
fruits={"apple": "蘋果", "grape": "葡萄", "peach": "桃子", "mango": "芒果"}
for value, text in fruits.items():                            # 用迴圈建立 Radiobutton 物件
    tk.Radiobutton(win, text=text,
                   variable=fruit,
                   value=value,
                   command=show_selection).pack()
label_result=tk.Label(text="", width=30, bg="ivory")         #顯示結果的 Label
label_result.pack()
win.mainloop()

此例定義了一個用來綁定 Radiobutton 群組的類別變數 fruit, 並且將其初始值任意設為各選項 value 參數值都沒有的 "none" 以便這些選項預設都沒有被選取. 然後以選項的值作為 key, 顯示文字作為 value 組成一個字典 fruits, 呼叫其 items() 方法便可傳回字典鍵值 tuple 組成之串列, 接著以 for 迴圈走訪此串列時建立 Radiobutton 元件, 結果如下 : 





可見 fruit.get() 傳回的是被選取的 Radiobutton 元件之 value 參數值, 此例的 fruits 字典將鍵與值設為不同值, 如果要讓傳回值與顯示值相同, 則可以將 text 與 value 參數設為相同, 這樣就不需要使用字典, 只要使用 tuple 或串列就可以了, 例如 :


測試 4 : 用串列搭配迴圈建立 Radiobutton 物件 [看原始碼]

import tkinter as tk
from tkinter import ttk

def show_selection():
    label_result["text"]="選擇結果: " + fruit.get()

win=tk.Tk()                                                      
win.title("tkinter GUI 測試") 
fruit=tk.StringVar()
fruit.set("none")
tk.Label(text="請選擇最喜歡的水果 : ", width=30, bg="cyan").pack()
fruits=["蘋果", "葡萄", "桃子", "芒果"]      # 兼做 text 與 value 參數值
for e in fruits:
    tk.Radiobutton(win, text=e,     
                   variable=fruit,
                   value=e,   
                   command=show_selection).pack()
label_result=tk.Label(text="", width=30, bg="ivory")
label_result.pack()
win.mainloop()

此例 text 與 value 參數都使用串列元素, 結果如下 : 




可見顯示的選取結果與選項的顯示文字是一樣的. 

下面範例測試 Radiobutton 元件的 indicatoron 參數, 此參數若設為 0 就會將選項以按鈕形式表示, 否則就以預設的圓鈕顯示, 不過此參數僅 tk 版有, ttk 不支援 : 


測試 5 : 用串列搭配迴圈建立 Radiobutton 物件 [看原始碼]

import tkinter as tk
from tkinter import ttk

def show_selection():
    label_result["text"]="選擇結果: " + fruit.get()

win=tk.Tk()                                                      
win.title("tkinter GUI 測試") 
fruit=tk.StringVar()
fruit.set("none")
tk.Label(text="請選擇最喜歡的水果 : ", width=30, bg="cyan").pack()
fruits=["蘋果", "葡萄", "桃子", "芒果"]
for e in fruits:
    tk.Radiobutton(win, text=e,
                   variable=fruit,
                   value=e,
                   indicatoron=0,    
                   command=show_selection).pack()
label_result=tk.Label(text="", width=30, bg="ivory")
label_result.pack()
win.mainloop()

結果如下 : 




下面範例測試 Radiobutton 元件的 width, height, 以及 background/bg 參數 : 


測試 6 : 測試 Radiobutton 元件的 width, height 與 bg 參數 [看原始碼]

import tkinter as tk
from tkinter import ttk

def show_selection():
    label_result["text"]="選擇結果: " + fruit.get()

win=tk.Tk()                                                      
win.title("tkinter GUI 測試") 
fruit=tk.StringVar()
fruit.set("none")
tk.Label(text="請選擇最喜歡的水果 : ", width=30, bg="cyan").pack()
fruits={"蘋果": "pink", "葡萄": "yellow", "桃子": "#654321", "芒果": "lime"}   
for value, bg in fruits.items():
    tk.Radiobutton(win, text=value,
                   variable=fruit,
                   value=value,
                   width=20,
                   height=2,
                   bg=bg,
                   command=show_selection).pack()
label_result=tk.Label(text="", width=30, bg="ivory")
label_result.pack()
win.mainloop()

此例使用字典來儲存水果選項名稱與其背景色之鍵值對, 然後以 for 迴圈走訪字典的 items() 方法傳回之 tuple 串列時設定各選項之背景色, 結果如下 : 




要注意的是 width 與 height 單位都是字元數, 不是 px. 

下面範例測試 textvariable 參數, 此參數透過所綁定的類別變數 (通常是 StringVar) 用來控制選項圓鈕旁的顯示文字, 注意, 設定了 textvariable 參數後, text 參數就無效了, 例如 : 


測試 7 : 測試 Radiobutton 元件的 textvariable 參數 [看原始碼]

import tkinter as tk
from tkinter import ttk

def show_selection():
    result_label.config(text="性別: " + gender.get())
def english():
    option1.set("Male")
    option2.set("Female")
def chinese():
    option1.set("男")
    option2.set("女")    

win=tk.Tk()                                                      
win.title("tkinter GUI 測試") 
gender=tk.StringVar()
gender.set("none")
option1=tk.StringVar()    # 用來綁定到選項的 textvariable 參數
option1.set("男")
option2=tk.StringVar()    # 用來綁定到選項的 textvariable 參數
option2.set("女")
ttk.Label(text="性別 : ", width=30, background="cyan").pack()
ttk.Radiobutton(win, 
               variable=gender,
               textvariable=option1,
               value="M",
               command=show_selection).pack()
ttk.Radiobutton(win, 
               variable=gender,
               textvariable=option2,    
               value="F",
               command=show_selection).pack()
result_label=ttk.Label(text="性別 : ", width=30, background="ivory")
result_label.pack()
ttk.Button(win, text="英文", command=english).pack(side="left")
ttk.Button(win, text="中文", command=chinese).pack(side="right")
win.mainloop()

此例的兩個選項設定了 textvariable 參數, 分別綁定到 option1 與 option2 這兩個 StringVar 類別變數, 因此就不需要設定 text 參數了. 選項顯示文字預設為中文, 當按下 "英文" 鈕時呼叫 english() 函式將 option1 與 option2 改為英文顯示, 結果如下 :






參考 :


沒有留言 :