今天繼續測試使用者輸入元件之選項圓鈕 (radio), 此為單選元件, 實際上會渲染為 HTML 中 type 為 radio 的 input 元件.
呼叫 Streamlit 的 radio() 函式並傳入會建立一組選項圓鈕元件, 當按下按鈕時傳回 True, 否則傳回 False, 其參數結構如下 :
st.radio(label, options, index=0, format_func=str, key=None, help=None, on_change=None, args=None, kwargs=None, disabled=False, horizontal=False, captions=None)
參數說明如下表 :
| st.radio() 之參數 | 說明 |
|---|---|
| label | 元件標籤文字,顯示於 radio 上方(必填) |
| options | 選項資料(list、tuple 或其他 iterable,必填) |
| index | 預設選中選項的索引,預設為 0 |
| format_func | 格式化選項顯示用的函式,預設為 str |
| key | 元件的唯一識別鍵,防止重複 |
| help | 當滑鼠移至元件上方時顯示的提示文字 |
| on_change | 選項變更時要呼叫的 callback 函式 |
| args / kwargs | 傳給 on_change 函式的位置參數 / 關鍵字參數 |
| disabled | 設為 True 時元件將無法互動 |
| horizontal | 設為 True 時選項會橫向排列,預設為垂直 |
| captions | 搭配圖片選項使用,提供對應的描述文字 |
其中 label 與 options 是必要之位置參數, label 是用來顯示在各選項上方的說明文字, options 則是列舉之選項文字, 可以是任何序列物件, 例如 list, tuple, Series 物件等.
# st-radio-test-1.py
import streamlit as st
label='請選擇最喜歡的水果 : '
options=['蘋果', '葡萄', '桃子', '芒果']
selection=st.radio(label, options)
st.write("你選的是:", selection)
此例僅傳入必要參數 label 與 options, 被選擇之選項值會立即傳回來, 因此不需要用一個按鈕去取得傳回值, 結果如下 :
可見預設選項是由上而下垂直排列, 如果要讓選項水平排列則要傳入 horizontal=True :
測試 2 : 傳入 horizontal=True 使選項水平排列 [看原始碼]
# st-radio-test-2.py
import streamlit as st
label='請選擇最喜歡的水果 : '
options=['蘋果', '葡萄', '桃子', '芒果']
selection=st.radio(label, options, horizontal=True)
st.write("你選的是:", selection)
結果如下 :
Streamlit 的選項圓鈕的傳回值就是被選擇選項的顯示字串, 如果想要讓傳回值與顯示字串不同 (即 input 元件中設定 value 屬性), 就要利用 format_func 參數指定一個自訂函式來轉換, 例如上面範例的四種水果我們想讓傳回值是英文, 則 options 參數就要改用英文 :
options=['apple', 'grape', 'peach', 'mango']
然後再定義一個字典來讓 format_func 參數指定的一個自訂函式來查詢轉換為顯示值 :
fruits={'apple': '蘋果', 'grape': '葡萄', 'peach': '桃子', 'mango': '芒果'}
程式碼如下 :
測試 3 : 利用 format_func 參數轉換選項之顯示字串 [看原始碼]
# st-radio-test-3.py
import streamlit as st
label='請選擇最喜歡的水果 : '
options=['apple', 'grape', 'peach', 'mango']
fruits={'apple': '蘋果', 'grape': '葡萄', 'peach': '桃子', 'mango': '芒果'}
selection=st.radio(label, options, format_func=lambda x: fruits[x])
st.write("你選的是:", selection)
此例傳入的 options 是英文的水果名稱, 所以傳回值就是英文, 但顯示值則是被 format_func 所指定之 lambda 函式轉換成中文, 此匿名函式會走訪 options 串列, 並將其元素傳給 lambda 中的參數 x, 以此為鍵查詢 fruits 字典而傳回中文水果名作為選項的顯示文字, 結果如下 :
可見雖然選項是中文, 但傳回值卻是英文.
上面範例也可以用 on_change 搭配 key 參數來做, 例如 :
測試 4 : 利用 on_change 與 key 參數轉換選項之傳回值 [看原始碼]
# st-radio-test-4.py
import streamlit as st
def on_radio_change():
selected=st.session_state['fruit_choice']
fruits={'蘋果': 'apple', '葡萄': 'grape', '桃子': 'peach', '芒果': 'mango'}
st.write(f'你選的是:{fruits[selected]}')
label='請選擇最喜歡的水果 : '
options=['蘋果', '葡萄', '桃子', '芒果']
st.radio(label, options, key='fruit_choice', on_change=on_radio_change)
此例中的 options 使用中文, 故在呼叫 st.radio() 時其顯示文字與傳回值都是中文水果名, 但我們另外傳入 key 參數與 on_change 參數, on_change 用來指定一個自訂函式來處理選項切換事件, key 則是為被選擇之選項設定一個獨一無二的鍵名, 它與被選擇的選項值會存入 st.session_state 字典中, 因此在切換事件處理函式中可以用 st.session_state[key] 取得選項圓鈕的傳回值, 然後從 fruits 字典中取得其英文, 結果如下 :
與上面範例不同的是, 初始化時不會顯示預設被選取項目, 而是要在選取動作發生時才會更新選取結果. 也可以在 on_change 事件發生時利用 args 參數攜帶引數給事件處理函式, 例如 :
測試 5 : 利用 args 參數攜帶引數給 on_change 事件處理函式 [看原始碼]
# st-radio-test-5.py
import streamlit as st
def on_radio_change(name):
selected=st.session_state['fruit_choice']
fruits={'蘋果': 'apple', '葡萄': 'grape', '桃子': 'peach', '芒果': 'mango'}
st.write(f'{name} 選的是:{fruits[selected]}')
label='請選擇最喜歡的水果 : '
options=['蘋果', '葡萄', '桃子', '芒果']
st.radio(label, options, key='fruit_choice', on_change=on_radio_change, args=('Tony',))
注意, args 參數型態為 tuple, 因此若只有一個元素後面必須有一個逗號. on_change 事件處理函式用一個參數來接收 args 傳遞的引數 (如果有兩個引數就兩個參數接收, 依序), 結果如下 :
也可以使用 kwargs 參數傳送, 例如 :
測試 6 : 利用 kwargs 參數攜帶引數給 on_change 事件處理函式 [看原始碼]
# st-radio-test-6.py
import streamlit as st
def on_radio_change(name=None):
selected=st.session_state['fruit_choice']
fruits={'蘋果': 'apple', '葡萄': 'grape', '桃子': 'peach', '芒果': 'mango'}
st.write(f'{name} 選的是:{fruits[selected]}')
label='請選擇最喜歡的水果 : '
options=['蘋果', '葡萄', '桃子', '芒果']
st.radio(label, options, key='fruit_choice', on_change=on_radio_change, kwargs={'name': 'Tony'})
此例與上面 args 的範例差別僅是 kwargs 使用字典傳送而已, 結果如下 :
有些應用場景可能需要同時使用 args 與 kwargs, 這時事件處理函式中的接收參數必須 args 位置參數在前 (依序), kwargs 關鍵字參數在後 (可以不依序).
下面是兩個 st.radio 元件連動的範例, 當變更第一個 st.radio 時, 第二個 st.radio 的選項也會動態改變 :
測試 7 : 兩個連動的 st.radio 選擇器 [看原始碼]
# st-radio-test-7.py
import streamlit as st
st.subheader('連動的 st.radio 選單測試')
# 圖片尺寸選項
food_options={
'米食': ['炒飯', '蛋包飯', '咖哩飯'],
'麵食': ['炒麵', '烏龍麵', '鍋燒麵']
}
# 初始化 session 狀態變數 : 預設=米食之炒飯
if 'main_sel' not in st.session_state:
st.session_state.main_sel='米食' # 預設米食
if 'item_sel' not in st.session_state:
st.session_state.item_sel=food_options['米食'][0] # 預設炒飯
# 主食選單(更新連動食譜選單)
main=st.radio(
'選擇主食',
['米食', '麵食'],
index=['米食', '麵食'].index(st.session_state.main_sel)
)
# 當主食選項更改時更新狀態變數
if main != st.session_state.main_sel:
st.session_state.main_sel=main # 更新主食狀態
st.session_state.item_sel=food_options[main][0] # 更新品項狀態為第一個被選取
# 品項選單 (會依主食動態變化)
item_sel=st.radio(
'選擇品項',
food_options[st.session_state.main_sel], # 依據主食設定品項的選項
index=food_options[st.session_state.main_sel].index(st.session_state.item_sel)
)
st.session_state.item_sel=item_sel # 更新食譜狀態
st.write(f'{st.session_state.main_sel}:{st.session_state.item_sel}'
此例利用 st.session_state 字典來記錄兩個選項園鈕的即時選項狀態, 當主選擇器 (主食) 變更選項時, 副選擇器 (品項) 的選項也隨之變更, 結果如下 :








沒有留言 :
張貼留言