2025年6月28日 星期六

Python 學習筆記 : 簡單好用的 Web app 套件 gradio (十)

最近幾天在測試 OpenAI Image API 時因為要用到兩個連動的 gr.Radio 元件, 學到了 gr.update() 函式的用法, 因此對此函式用法做了一番測試並紀錄如下.

本系列全部文章索引參考 :


函式 gr.update() 用來更新元件的屬性, 用來在互動式應用中動態更新 Gradio 使用者介面元件的屬性 (不是重建整個元件), 例如點擊按鈕, 改變選單之選項, 元件預設值, 顯示或隱藏元件等等, 無需重新載入整個介面, 其參數結構如下 : 

gr.update(
    value=None,                # 更新元件的值(例如文字、選取項目等)
    choices=None,             # 更新選單元件的選項(例如 Dropdown, Radio 等)
    visible=True,               # 是否顯示元件(True=顯示, False=隱藏)
    interactive=True,         # 是否可互動(False=禁用元件)
    label=None,                 # 更新元件的標籤文字
    info=None,                  # 更新元件下方的說明文字
    elem_id=None,             # 更新 HTML 元素 ID
    elem_classes=None,     # 更新 HTML class 名稱(list of str)
    container=None,           # 是否包裝在容器中(通常用不到)
    scale=None,                  # 控制元件所佔水平空間比例
    min_width=None,        # 設定元件最小寬度(px)
    render=True                 # 是否渲染此變更(預設 True)
    )

參數說明如下表 :


參數名稱 說明
value 更新元件的值,例如文字內容、選取項目或輸入數字等
choices 適用於 Dropdown、Radio 等元件,用來更新選項列表
visible 是否顯示元件,True 為顯示,False 為隱藏
interactive 是否可互動,False 時會讓元件變成唯讀或無法點擊
label 更新元件的標籤文字
info 更新元件下方顯示的說明資訊
elem_id 更新元件的 HTML 元素 ID,可用於自訂樣式或 JS 操作
elem_classes 更新 HTML class 名稱,可為字串或字串列表,用於自訂樣式
container 是否顯示外層容器,通常保留預設值即可
scale 控制元件在橫向空間中所佔比例,用於區塊佈局(0~1)
min_width 設定元件最小寬度(像素),超過該寬度才會換行
render 是否立即渲染更新,預設為 True


下列 UI 元件之事件方法常用來觸發呼叫 gr.update() 函式去動態更新元件之屬性 :


常用事件方法 說明
click() 按下按鈕時觸發,常用於 gr.Button
change() 當元件值改變時觸發,例如 Dropdown、Radio、Slider 等
submit() 當使用者在 Textbox 按 Enter 鍵時觸發
blur() 當元件失去焦點(如離開輸入框)時觸發
input() 使用者輸入時即時觸發(如每輸入一字)
release() 滑鼠釋放時觸發,常用於 Slider 或繪圖板元件


最常用的是按鈕元件的 click() 或 submit() 方法與選項元件 (Radio, Checkbox, Dropdown) 勾選動作觸發的 change() 方法. 最重要的一點是, UI 元件必須放在 gr.Blocks 語境內才能動態更新, gr.Interface 只處理輸入到輸出的靜態網頁, 無法做元件屬性變更. 

例如 : 


測試 1 : 按鈕的 click 事件更新文字框之顯示或隱藏狀態 (1) [看原始碼]

# gradio-update-test-2.py
import gradio as gr

def show_textbox():
    return gr.update(visible=True)  # 傳回 Update 物件

def hide_textbox():
    return gr.update(visible=False)  # 傳回 Update 物件

with gr.Blocks() as blocks:
    show_btn=gr.Button('顯示輸入框')
    hide_btn=gr.Button('隱藏輸入框')
    textbox=gr.Textbox(label='輸入框', visible=False)  # 文字框預設為隱藏
    show_btn.click(fn=show_textbox, inputs=[], outputs=textbox)
    hide_btn.click(fn=hide_textbox, inputs=[], outputs=textbox)
blocks.launch()

此例用兩個按鈕 show_btn 與 hide_btn 分別用來控制文字框的顯示與隱藏 (文字框預設為隱藏), 當按下這兩個按鈕時會分別呼叫 show_textbox() 與 hide_text(), 這兩個函式都是呼叫 gr.update() 後將結果傳回給 outputs 所指定的元件 (即 show_textbox 與 hide_textbox 文字框), gr.update() 會傳回一個攜帶指定屬性 visible 的 Update 物件, 文字框收到此 Update 物件後就會根據此 Update 物件之屬性去修改自己的屬性 (即 visible=True/False), 所以 Update 物件相當於一個 modify 指令. 注意, 此處因為 click 事件的處理函式不需要輸入元件的資訊, 因此 inputs 傳入空串列即可. 結果如下 : 

按上面按鈕顯示輸入框 :




按下面按鈕隱藏輸入框 :




其實可以只用一個按鈕達成同樣功能, 例如 : 


測試 2 : 按鈕的 click 事件更新文字框之顯示或隱藏狀態 (2) [看原始碼]

# gradio-update-test-2.py
import gradio as gr

def handler(showing):
    new_state=not showing  # 狀態交替:True → False、False → True
    return (  # 根據新狀態回傳更新指令 (傳回 Update 與 State 物件)
        gr.update(visible=new_state),  # 更新 textbox 是否顯示
        gr.update(value='隱藏文字框' if new_state else '顯示文字框'),  # 更新按鈕文字
        new_state  # 更新狀態紀錄
        )

with gr.Blocks() as blocks:
    state=gr.State(False)  # 初始狀態為 False(隱藏文字框)
    btn=gr.Button('顯示文字框')
    textbox=gr.Textbox(label='輸入框', visible=False)  # 文字框預設隱藏
    # outputs: textbox, btn, state (順序對應 handler 回傳值)
    btn.click(fn=handler, inputs=state, outputs=[textbox, btn, state])
blocks.launch()

此例僅用一個按鈕 btn 來控制輸入框之顯示, 並使用 State 物件紀錄文字框的狀態, 當按下按鈕時將此物件傳給 inputs 參數, 讓 handler() 依據此 State 物件來交替狀態, 注意, handler() 的傳回值 (兩個 Update 物件與一個 State 物件) 順序必須對應 click() 的 outputs 參數串列之順序. 當 outputs 所列的輸出元件收到這三個物件後會根據物件內容更新自己的屬性值 (True/False), 結果如下 :




也可以用 gr.Checkbox 元件來控制輸入框顯示與否, 例如 :


測試 3 : 選項元件的 change 事件更新文字框之顯示或隱藏狀態 (2) [看原始碼]

# gradio-update-test-3.py
import gradio as gr

def handler(showing):  # 傳入輸入元件之值 True/False
    return gr.update(visible=showing)  # 傳回 Update 物件

with gr.Blocks() as blocks:
    checkbox=gr.Checkbox(label='顯示輸入框')
    textbox=gr.Textbox(label='輸入框', visible=False)  # 預設隱藏
    checkbox.change(fn=handler, inputs=checkbox, outputs=textbox)
blocks.launch()

此例利用 gr.Checkbox 元件有無勾選來控制文字輸入框之顯示與否, 勾選動作會觸發 change 事件呼叫 handler() 函式來處理, 傳入參數 inputs 就是這個 Checkbox 物件, change() 會先抽取此物件之值 (True/False) 再傳給 handler(), 因此 handler() 接收到的 showing 參數是 True/False, 它會傳回一個攜帶 visible 屬性的 Update 物件, 傳回給 outputs 所指的輸入框物件 textbox 後即依據此屬性更改輸入框的 visible 狀態, 結果如下 :




Checjbox 預設不勾選, 輸入框是隱藏的; 勾選後就會顯示輸入框了. 

沒有留言 :