2021年9月16日 星期四

Python 內建 GUI 模組 tkinter 測試 (十四) : Combobox 元件

今天繼續測試的 Combobox (下拉式選單) 元件. 

本系列之前的文章參考 :   


Combobox 元件 (下拉式選單) 與 Spinbox 類似, 也是一種複合元件, 由 Entry 與附捲軸之 Listbox 組成, 可讓使用者在下拉清單中選取一個選項,  也可以直接在 Entry 中輸入內容. 注意, 此元件僅在 ttk 中有, tk 中無此元件. 建立 Combobox 元件之語法如下 : 

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



Combobox 元件常用參數如下表 : 


 Combobox 常用參數 說明
 width Combobox 輸入 Entry 的寬度 (字元數, 預設 20 個字元)
 height 設定下拉式選單最大顯示列數 (預設 20), 超出會顯示捲軸
 values 設定下拉式選單之選項, 可用字串之元組或串列 
 textvariable 與 Combobox 綁定之類別變數名稱 (通常用 StringVar)
 state 設定 Combobox 狀態 : NORMAL (預設)/DISABLED/READONLY


注意, state 參數也可以使用字串 "normal", "disabled", 或 "readonly". 

Combobox 元件常用方法如下 :


 Combobox 常用方法 說明
 get() 取得 Combobox 元件之現值
 set(option) 設定選項 option 為被選取
 current([index]) 設定索引=index 之項目被選取, 未傳入參數則傳回被選取項之索引


取得 Combobox 被選取之現值除了呼叫 Combobox 物件的 get() 方法外, 也可以呼叫與其 textvariable 參數綁定的類別變數之 get() 方法. 

建立 Combobox 元件時只要傳入 values 參數即可, 例如 : 


測試 1 : 預設的 Combobox 下拉式選單 [看原始碼]

import tkinter as tk
from tkinter import ttk

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")
win.geometry("300x200")

values_1=("岳不群", "左冷禪", "定逸師太", "任盈盈", "令狐沖") 
combobox_1=ttk.Combobox(win, values=values_1)
combobox_1.pack()
values_2=["張無忌", "趙敏", "楊不悔", "朱九貞", "周芷若"]
combobox_2=ttk.Combobox(win, values=values_2)
combobox_2.pack()
win.mainloop()

此例的兩個下拉式選單分別以 list 與 tuple 形式傳入 values 參數, 結果如下 : 




此例僅設定 values 參數, 預設 Entry 寬度為 20 個字元, 看來有點寬, 這可以用 width 參數設定, 下面範例同時也指定了 height 參數來限制最大顯示列數 :


測試 2 : 設定 width (輸入區寬度) 與 height (清單顯示列數) 參數 [看原始碼]

import tkinter as tk
from tkinter import ttk

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")
win.geometry("300x200")

values_1=("岳不群", "左冷禪", "定逸師太", "任盈盈", "令狐沖") 
combobox_1=ttk.Combobox(win, values=values_1, width=10, height=3)
combobox_1.pack()
values_2=["張無忌", "趙敏", "楊不悔", "朱九貞", "周芷若"]
combobox_2=ttk.Combobox(win, values=values_2, width=10, height=3)
combobox_2.pack()
win.mainloop()

此例添加了 width 與 height 參數, 結果如下 : 




可見下拉式清單只顯示三個選項, 這時清單會自動出現捲軸, 方便點選其他位顯示之選項. 

如果要取得被選取的選項可呼叫 Combobox 物件的 get() 方法, 呼叫 set() 方法則可指定某選項為被選取, 而呼叫 current() 則可傳回被選取選項之索引, 例如 :


測試 3 : 呼叫 get(), set(), 與 current() 方法存取被選取之選項 [看原始碼]

import tkinter as tk
from tkinter import ttk

def show_value():
    label["text"]="選取 : " + combobox.get() + \
                  " 索引 : " + str(combobox.current())        # 取得被選取選項與其索引

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")
win.geometry("300x200")

values=("Python", "Javascript", "R", "Julia", "PHP")
combobox=ttk.Combobox(win, values=values)
combobox.pack()
combobox.set("Python")        # 設定被選取選項
ttk.Button(win, text="確定", command=show_value).pack()
label=ttk.Label(win)
label.pack()
win.mainloop()

此例在建立 Combobox 物件後呼叫其 set() 方法將選項 "Python" 設定為預設被選取項目. 按下確定鈕時其 command 觸發按鈕事件, 呼叫 Combobox 的 get() 方法取得被選取之選項, current() 方法則傳回該項目之索引, 結果如下 :





除了呼叫 Combobox 物件的 get() 方法取得被選取之選項外, 還可以利用 textvariable 參數綁定一個 StringVar 類別變數, 透過其 get() 方法也可以取得被選擇之選項, 而且呼叫類別變數的 set() 亦可設定 Combobox 的預設選項, 例如 :


測試 4 : 用 textvariable 綁定類別變數來存取 Combobox [看原始碼]

import tkinter as tk
from tkinter import ttk

def show_value():
    label["text"]=var.get()        # 呼叫類別變數的 get() 方法取得被選取項目

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")
win.geometry("300x200")

var=tk.StringVar()          # 與 Combobox 綁定之類別變數
var.set("Python")            # 設定預設被選取選項
values=("Python", "Javascript", "R", "Julia", "PHP")
combobox=ttk.Combobox(win, values=values, textvariable=var)    # 綁定類別變數
combobox.pack()
ttk.Button(win, text="確定", command=show_value).pack()
label=ttk.Label(win)
label.pack()
win.mainloop()

此例利用 textvariable 參數綁定一個類別變數 var, 呼叫其 set() 方法可設定被選取之項目, 呼叫 get() 則可取得被選取項目, 結果如下 :





由於 Combobox 沒有像 Spinbox 那樣提供 command 參數, 故上面範例都需要一個按鈕來觸發事件. 不過可以利用 Tkinter 的事件處理機制, 透過元件的 bind() 方法替 ComboboxSelected 事件綁定一個處理函式, 就可以在選取時觸發事件, 例如 :


測試 5 : 呼叫 bind() 方法綁定 ComboSelected 事件處理函式 [看原始碼]

import tkinter as tk
from tkinter import ttk

def show_value(value):
    label["text"]=var.get()

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")
win.geometry("300x200")

var=tk.StringVar()
var.set("Python")
values=("Python", "Javascript", "R", "Julia", "PHP")
combobox=ttk.Combobox(win, values=values, textvariable=var)
combobox.bind('<<ComboboxSelected>>', show_value)
combobox.pack()
label=ttk.Label(win)
label.pack()
win.mainloop()

此例呼叫 Combobox 物件的 bind() 方法為 ComboSelected 事件綁定處理函式, 當使用者選取項目時就會觸發此事件, 不需透過額外的按鈕, 結果如下 :





Tkinter 元件之事件處理參考 :


下面範例測試 state 參數, 預設 "normal" 表示 Combobox 除了可從下拉式選單中選擇項目外, 也可以直接在 Entry 中直接輸入清單以外的任何內容; 若設為 "readonly" 表示只能從下拉式選單中挑選項目, 不能直接輸入; 若設為 "disabled" 則表示禁能, 連下拉式選單也無法使用, 例如 :


測試 6 : 將 state 參數設為 "readonly" [看原始碼]

import tkinter as tk
from tkinter import ttk

def show_value_1():
    label_1["text"]=combobox_1.get()
def show_value_2():
    label_2["text"]=combobox_2.get()

win=tk.Tk()                                                      
win.title("tkinter GUI 測試")
win.geometry("300x200")

values=("Python", "Javascript", "R", "Julia", "PHP")
combobox_1=ttk.Combobox(win, values=values)
combobox_1.pack()
ttk.Button(win, text="確定", command=show_value_1).pack()
label_1=ttk.Label(win)
label_1.pack()
combobox_2=ttk.Combobox(win, values=values, state="readonly")   # 無法直接輸入
combobox_2.pack()
ttk.Button(win, text="確定", command=show_value_2).pack()
label_2=ttk.Label(win)
label_2.pack()
win.mainloop()

此例有兩個 Combobox 元件, combobox_1 未設定 state 參數, 預設為 "normal", 故可輸入可挑選; 但 combobox_2 則設為 "readonly", 無法輸入只能挑選, 結果如下 :




可見點上面的 Combobox 可以輸入任何內容, 但下面的 Combobox 因為是唯讀, 故一點其 Entry 馬上就跳出選單, 無法輸入內容. 

參考 :


沒有留言:

張貼留言