如何自定义Streamlit Expander组件?解决Label无法渲染标注文本问题
解决Streamlit st.expander标签无法渲染HTML/自定义组件的方案
st.expander的label参数仅支持纯文本或基础Markdown,无法直接渲染HTML或annotated_text这类自定义组件生成的带样式标签,导致你的代码会把标注组件的原始HTML字符串直接显示出来。以下是两种可行的替代方案:
方案一:用原生HTML <details> 标签模拟折叠效果
利用Streamlit的st.markdown支持渲染HTML的特性,用原生的<details>和<summary>标签实现和expander一致的折叠功能,<summary>里可直接放入annotated_text生成的HTML内容:
import streamlit as st from annotated_text import annotation # 假设已定义context、start_idx、end_idx、answer变量 annotated_segment = str(annotation(f"**{answer}**", "ANSWER", "#ff0074")) full_label = f"{context[:start_idx]}{annotated_segment}{context[end_idx:]}" # 渲染带折叠功能的HTML st.markdown(f""" <details style="margin: 1rem 0;"> <summary>{full_label}</summary> <div style="margin-top: 1rem; padding-left: 1rem;"> <!-- 放入原本在expander内的内容 --> <p>这是展开后的内容示例</p> <code>支持HTML格式内容</code> </div> </details> """, unsafe_allow_html=True)
注意:该方案无法在折叠区域内直接嵌套Streamlit原生组件(如st.button、st.dataframe等),需要这类组件的话可使用方案二。
方案二:结合会话状态实现可交互的自定义折叠控件
通过Streamlit会话状态控制内容显示,同时用自定义HTML渲染带标注的折叠触发标签,支持所有原生组件:
import streamlit as st from annotated_text import annotation # 初始化会话状态,记录折叠状态 if "custom_expander_open" not in st.session_state: st.session_state.custom_expander_open = False # 生成带标注的HTML标签 annotated_segment = str(annotation(f"**{answer}**", "ANSWER", "#ff0074")) full_label = f"{context[:start_idx]}{annotated_segment}{context[end_idx:]}" # 渲染可点击的折叠标签,点击触发状态切换 st.markdown(f""" <div style="cursor: pointer; padding: 0.5rem; border: 1px solid #e0e0e0; border-radius: 0.25rem;" onclick="window.parent.postMessage('toggle_expander', '*')"> {full_label} <span style="float: right;">{'▼' if st.session_state.custom_expander_open else '▶'}</span> </div> """, unsafe_allow_html=True) # 监听前端消息,切换会话状态 st.components.v1.html(""" <script> window.addEventListener('message', (e) => { if (e.data === 'toggle_expander') { const currentState = window.parent.stSessionState.custom_expander_open; window.parent.document.dispatchEvent(new CustomEvent('streamlit:setComponentValue', { detail: { key: 'custom_expander_open', value: !currentState } })); } }); </script> """, height=0) # 根据状态显示/隐藏折叠内容 if st.session_state.custom_expander_open: # 放入原本在expander内的代码 st.write("展开后的原生Streamlit组件") st.button("测试按钮") st.dataframe({"列1": [1,2,3], "列2": [4,5,6]})
内容的提问来源于stack exchange,提问作者stanly
相关产品推荐
相关产品推荐

