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

如何解决Streamlit中Bokeh滑块无法联动图片展示的问题?

问题原因与解决方案

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

  • 嵌入到Streamlit的Bokeh应用是静态HTML,Python回调函数change_img无法执行,必须改用JavaScript回调直接操作前端元素。
  • 你当前的JS回调只更新了ColumnDataSource,完全没处理logo这个Div组件,所以滑块变动不会触发图片更新。

另外,代码里的柱状图figure和ColumnDataSource是多余的,完全可以删掉以简化逻辑。

修正后的完整代码如下:

import streamlit as st
import streamlit.components.v1 as components
from bokeh.embed import file_html
from bokeh.layouts import column
from bokeh.models import CustomJS, Slider, Div
from bokeh.resources import CDN

def plot(p=1):
    # 初始化图片Div
    logo = Div(
        text=f"""<img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/{p}.png" 
                alt="logo" width="200" height="200">""",
        width=200, height=200
    )

    # 初始化滑块
    slider = Slider(
        start=1, end=10, value=p, step=1, title="image number"
    )

    # 给滑块绑定JS回调,直接操作logo组件
    slider.js_on_change(
        "value",
        CustomJS(
            args=dict(logo=logo),  # 将logo对象传入JS环境
            code="""
                // 获取滑块当前值
                const imgNum = cb_obj.value;
                // 更新Div的text内容,替换图片URL中的数字
                logo.text = `<img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${imgNum}.png" 
                            alt="logo" width="200" height="200">`;
            """
        ),
    )

    # 返回嵌入用的HTML
    return file_html(column(logo, slider), CDN)

components.html(plot(), height=400)

关键修改说明:

  1. 移除冗余组件:删掉了不需要的figure和ColumnDataSource,聚焦滑块控制图片的核心需求。
  2. 改用JS回调:把原来的Python回调换成CustomJS,直接在前端修改Div的内容,避免Streamlit全量重跑。
  3. 传递目标组件:在CustomJS的args里传入logo对象,让JS代码可以直接访问并修改这个Div的text属性。
  4. 优化嵌入高度:调整components.html的height为400,更贴合实际内容高度。

这样修改后,滑块拖动时会立刻触发JS代码更新图片,不会触发Streamlit的全量重跑,速度和原生Bokeh应用一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:22:38