2025年5月19日 星期一

Streamlit 學習筆記 : 使用者輸入元件 (四) 單選下拉式選單

本篇旨在測試使用者輸入元件之單選下拉式選單 (selectbox), 此元件與單選圓鈕功能一樣, 都是從多個選項中只選出一個. 

本系列所有測試文章參考 :


呼叫 Streamlit 的 selectbox() 函式並傳入 label 與 options 參數會建立一個單選下拉式選單, 預設會顯示第一個項目, 點選某一項目後會傳回該項目值, 其參數結構如下 : 

st.selectbox(label, options, index=0, format_func=str, key=None, help=None,on_change=None, args=None, kwargs=None, disabled=False, label_visibility="visible", placeholder=None) 

參數說明如下表 :


st.selectbox() 之參數 說明
label 元件的標籤文字,顯示在選單上方。
options 可選項目(list、tuple、np.array、Series 等)。
index 預設選取項目的索引,預設為 0。
format_func 自訂顯示選項的函式,預設為 str。
key 唯一鍵值,避免與其他元件衝突。
help 顯示在 label 旁的說明提示。
on_change 使用者改變選取內容時要呼叫的函式。
args 傳給 on_change 的位置參數 (tuple)。
kwargs 傳給 on_change 的關鍵字參數 (dict)。
disabled 設為 True 時元件會被停用。
label_visibility 控制 label 顯示方式:'visible'(預設)、'hidden' 或 'collapsed'。
placeholder 未選取任何項目時顯示的提示文字。


其中 label 與 options 是必要之位置參數, 其餘為關鍵字參數. label 用來顯示在下拉式選單上方的說明文字, options 則是列舉之選項文字, 可以是任何序列物件, 例如 list, tuple, Series 物件等. 

例如 : 


測試 1 : 只傳入必要參數 label 與 options [看原始碼] 

# st-selectbox-test-1.py
import streamlit as st

label='請選擇最喜歡的水果 : '
options=['蘋果', '葡萄', '桃子', '芒果']
selection=st.selectbox(label, options)
st.write("你選的是:", selection)

預設會顯示第一個項目 (index=0) '蘋果' : 




點右方向下箭頭會展開選單, 點選 '葡萄' 後結果如下 :





可見 st.selectbox() 的傳回值就是被選取的顯示值. 如果要傳回與顯示值不同的值 (例如傳回英文水果名), 就要像單選圓鈕一樣, 利用 format_func 參數指定一個自訂函式來做格式轉換, 例如 : 


測試 2 : 利用 format_func 參數轉換選項之顯示字串 [看原始碼] 

# st-selectbox-test-2.py
import streamlit as st

label='請選擇最喜歡的水果 : '
options=['apple', 'grape', 'peach', 'mango']
fruits={'apple': '蘋果', 'grape': '葡萄', 'peach': '桃子', 'mango': '芒果'}
selection=st.selectbox(label, options, format_func=lambda x: fruits[x])
st.write("你選的是:", selection)

此例選項串列改為英文, 所以下拉式選單的傳回值式英文, format_func 參數指向一個 lambda 匿名函式, 它會走訪 options 串列中的每個英文選項 (x 變數), 然後查詢 fruits 字典中對應的中文後傳回, 所以下拉式選單顯示的是中文, 結果如下 : 




上面這個顯示中文傳回英文的範例也可以用 on_change 事件來做, 這需要搭配 Streamlit 跨執行記錄狀態的字典 st.session_state 與函式的 key 參數, Streamlit 會在背後隱匿地將元件的狀態 (值) 紀錄在以 key 為鍵的 st.session_state 字典中, 例如 :


測試 3 : 利用 on_change 與 key 參數轉換選項之傳回值 [看原始碼] 

# st-selectbox-test-3.py
import streamlit as st

def on_selectbox_change():
    selected=st.session_state['fruit_choice']  # 取得追蹤之 key 的狀態
    fruits={'蘋果': 'apple', '葡萄': 'grape', '桃子': 'peach', '芒果': 'mango'}
    st.write(f'你選的是:{fruits[selected]}')

label='請選擇最喜歡的水果 : '
options=['蘋果', '葡萄', '桃子', '芒果']
st.selectbox(label, options, key='fruit_choice', on_change=on_selectbox_change)

此例 options 改回中文水果串列, 當選取事件發生時, 傳回的被選取項目值會被記錄在 fruit_choice 的鍵裡面, 因此呼叫 on_selectbox_change() 便可取出此鍵之值從 fruits 字典中查出其英文名稱, 結果如下 : 




下面範例是測試在 on_change 事件發生時利用 args 參數攜帶引數給事件處理函式, 例如 : 


測試 4 : 利用 args 參數攜帶引數給 on_change 事件處理函式 [看原始碼] 

# st-selectbox-test-4.py
import streamlit as st

def on_selectbox_change(name):
    selected=st.session_state['fruit_choice']
    fruits={'蘋果': 'apple', '葡萄': 'grape', '桃子': 'peach', '芒果': 'mango'}
    st.write(f'{name} 選的是:{fruits[selected]}')

label='請選擇最喜歡的水果 : '
options=['蘋果', '葡萄', '桃子', '芒果']
st.selectbox(label, options, key='fruit_choice', on_change=on_selectbox_change, args=('Tony',))

此例 on_selectbox_change() 函式用一個參數 name 來接收 args 傳遞的引數 (如果有兩個引數就兩個參數接收, 依序). 注意, args 參數型態為 tuple, 因此若只有一個元素後面必須有一個逗號才行. 結果如下 :




上面這範例也可以改成用 kwargs 參數來傳送引數 :


測試 5 : 利用 kwargs 參數攜帶引數給 on_change 事件處理函式 [看原始碼] 

# st-selectbox-test-5.py
import streamlit as st

def on_selectbox_change(name=None):
    selected=st.session_state['fruit_choice']
    fruits={'蘋果': 'apple', '葡萄': 'grape', '桃子': 'peach', '芒果': 'mango'}
    st.write(f'{name} 選的是:{fruits[selected]}')

label='請選擇最喜歡的水果 : '
options=['蘋果', '葡萄', '桃子', '芒果']
st.selectbox(label, options, key='fruit_choice', on_change=on_selectbox_change, kwargs={'name': 'Tony'})

結果如下 :




由以上測試可知, st.selectbox() 功能其實與 st.radio() 幾乎一樣, 下拉式選單好處是選項都收合起來只顯示一個較不佔空間而已. 

接下來測試 placeholder 參數, 此參數是從 Streamlit 1.19 版開始加入的, 用來讓選單在初始化時不要顯示第一個選項, 而是 placeholder 所設定的字串, 但要達成此功能, 必須傳入 index=None 參數 (預設是 0, 顯示第一個選項), 例如 :


測試 6 : 用 placeholder 參數設定選項佔位文字 [看原始碼] 

# st-selectbox-test-6.py
import streamlit as st

label='請選擇最喜歡的水果 : '
options=['蘋果', '葡萄', '桃子', '芒果']
selection=st.selectbox(label, options, index=None, placeholder='請拉下選單選擇水果')
st.write("你選的是:", selection)

結果如下 : 




上面是初始化時的結果, 不是顯示第一個選項, 而是顯示 placeholder 的佔位文字. 下面則是選取後的結果. 

沒有留言 :