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

Streamlit_Calendar事件更新与日历重渲染问题求助

解决方案:Streamlit Calendar 事件更新与重渲染问题修复

问题根源分析

你的代码存在几个关键错误导致事件无法更新和日历重渲染:

  • 错误地将st.session_state["events"]当作字典访问(st.session_state["events"]["events"]),但初始的events是列表类型,而非嵌套字典。
  • 手动创建重复日历组件的做法多余,Streamlit会根据会话状态变化自动重渲染组件,无需额外实例化。
  • 新事件的资源键使用resource而非原有事件的resourceId,导致组件无法正确识别该字段。
  • 颜色值的capitalize()处理无意义,十六进制颜色不需要格式转换。

修正后的完整代码

import streamlit as st
from streamlit_calendar import calendar

# 页面配置
st.set_page_config(page_title="Demo for Streamlit Calendar", page_icon="📆")

# 初始化事件列表
if "events" not in st.session_state:
    st.session_state["events"] = [
        {
            "title": "Event 1",
            "color": "#FF6C6C",
            "start": "2024-06-03",
            "end": "2024-06-05",
            "resourceId": "a",
        },
        {
            "title": "Event 2",
            "color": "#FFBD45",
            "start": "2024-06-01",
            "end": "2024-06-10",
            "resourceId": "b",
        },
    ]

# 日历模式选择
mode = st.selectbox(
    "Calendar Mode:",
    ("daygrid", "timegrid", "timeline", "list"),
)

# 日历配置
calendar_options = {
    "editable": True,
    "navLinks": True,
    "selectable": True,
    "headerToolbar": {
        "left": "today prev,next",
        "center": "title",
        "right": "",
    },
    "initialDate": "2024-06-01",
}

# 根据模式设置初始视图
view_mapping = {
    "daygrid": "dayGridMonth",
    "timegrid": "timeGridWeek",
    "timeline": "timelineMonth",
    "list": "listMonth"
}
calendar_options["initialView"] = view_mapping[mode]
if mode in ["daygrid", "timeline"]:
    calendar_options["resourceGroupField"] = "building"

# 渲染日历组件
calendar_instance = calendar(
    events=st.session_state["events"],
    options=calendar_options,
    custom_css="""
    .fc-event-past { opacity: 0.8; }
    .fc-event-time { font-style: italic; }
    .fc-event-title { font-weight: 700; }
    .fc-toolbar-title { font-size: 2rem; }
    """,
    key=f"calendar_{mode}"
)

# 处理日历内部的事件修改(拖拽、编辑等)
if "eventsSet" in calendar_instance:
    st.session_state["events"] = calendar_instance["eventsSet"]

# 侧边栏事件管理
st.sidebar.header("Event Management")
event_title = st.sidebar.text_input("Event Title")
event_start_date = st.sidebar.date_input("Start Date", value=None)
event_end_date = st.sidebar.date_input("End Date", value=None)
event_color = st.sidebar.color_picker("Event Color", "#FF6C6C")

# 添加事件按钮逻辑
if st.sidebar.button("Add Event"):
    if event_title and event_start_date and event_end_date:
        new_event = {
            "title": event_title,
            "start": str(event_start_date),
            "end": str(event_end_date),
            "color": event_color,
            "resourceId": "c"  # 统一使用resourceId字段
        }
        st.session_state["events"].append(new_event)
        # 触发页面重渲染(Streamlit会自动处理,此处可添加提示)
        st.sidebar.success("事件已添加!")

# 可选:显示当前事件列表用于调试
# st.write("当前事件列表:", st.session_state["events"])

关键修改说明

  1. 修正事件列表访问方式:直接使用st.session_state["events"].append(new_event)添加新事件,因为初始的events是列表类型。
  2. 移除重复日历实例:删除手动创建updated_calendar_instance的代码,Streamlit会在会话状态更新后自动重新渲染日历组件。
  3. 统一资源字段:将新事件的resource改为resourceId,与原有事件字段保持一致,确保组件正确识别。
  4. 简化视图配置:使用字典映射替代冗余的条件判断,让代码更简洁。
  5. 添加成功提示:按钮点击后显示成功信息,提升用户体验。

额外说明

  • 日历组件的key设置为f"calendar_{mode}",确保切换模式时组件能正确重新初始化。
  • 保留了日历内部事件修改的处理逻辑(eventsSet),支持拖拽、编辑等操作后的事件同步。

内容的提问来源于stack exchange,提问作者vrishabh gupta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:04:54