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

Shiny for Python:多图渲染与动态删除功能实现故障排查

解决Python Shiny动态添加/删除图表的问题

你的代码核心问题有两个:

  1. 所有动态插入的图表共用同一个output id(plot_logic),导致新图表会覆盖旧图表的渲染逻辑,最终所有图表显示相同内容。
  2. 删除逻辑未绑定到单个按钮的点击事件,而是持续遍历所有按钮状态,不仅效率低,还会导致异常触发。

以下是修复后的完整代码:

from shiny import App, render, ui, reactive
import matplotlib.pyplot as plt


app_ui = ui.page_fluid(
    ui.row(
        ui.input_selectize('entry', 'User input', choices=[i for i in range(10)]),
        ui.input_action_button('submit', 'Submit'),
        id='selection_ui'
    )
)

def server(input, output, session):
    
    session_nb_plot = reactive.Value(0)
    
    @reactive.Effect
    @reactive.event(input.submit)
    def _add():
        entry = input.entry()
        nb_plot = session_nb_plot.get()
        
        # 生成唯一的ID标识
        plot_id = f"plot_{nb_plot}"
        remove_btn_id = f"remove_{nb_plot}"
        panel_id = f"to_remove_{nb_plot}"
        
        # 注册当前图表的渲染函数
        @output(id=plot_id)
        @render.plot
        def _():
            fig = plt.figure()
            plt.plot([entry], 'rD')  # 修正:将单个数字转为列表,确保绘制单个点
            return fig
        
        # 插入包含图表和删除按钮的面板
        ui.insert_ui(
            ui.panel_well(
                ui.input_action_button(remove_btn_id, 'Remove'),
                ui.output_plot(plot_id),
                id=panel_id
            ),
            selector='#selection_ui',
            where='afterEnd'
        )
        
        # 为当前删除按钮绑定专属移除事件
        @reactive.Effect
        @reactive.event(input[remove_btn_id])
        def _():
            ui.remove_ui(f'#{panel_id}')
            # 可选:注销对应的output,释放资源
            del output[plot_id]
        
        session_nb_plot.set(nb_plot + 1)


app = App(app_ui, server)

关键修复点说明:

  • 唯一ID生成:每次添加图表时,基于session_nb_plot生成唯一的plot_id、remove_btn_id和panel_id,确保每个图表和按钮都是独立的,避免ID冲突。
  • 动态注册Output:使用@output(id=plot_id)为每个图表注册专属的渲染函数,保证每个图表对应独立的渲染逻辑。
  • 绑定单个按钮事件:每个删除按钮创建时,单独绑定其点击事件,点击后仅移除对应面板,逻辑清晰且避免无效遍历。
  • 图表渲染修正:原代码中plt.plot(entry, 'rD')会将单个数字当作x轴范围,改为plt.plot([entry], 'rD')才能正确绘制单个点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:23:01