You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 16:39:56