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

如何在Bokeh中启用交互式CheckboxGroup?点击后阴影区域不显示问题

问题原因分析

你的代码有几个关键问题导致复选框点击后阴影区域没显示:

  1. 静态HTML无法运行Python回调:你用output_file()生成静态HTML文件,但.on_click()绑定的Python函数clicker属于服务器端回调——这种回调需要Bokeh Server才能执行,静态HTML里根本跑不了Python代码。

  2. 渲染器管理逻辑错误:就算用了Bokeh Server,每次点击都调用p.quad()会不断新增矩形,而不是切换已有元素的显示/隐藏;而且当没有勾选复选框时,直接访问checkbox_group.active[0]会抛出索引越界的错误。

  3. 缺少文档更新触发:服务器端回调需要明确通知文档更新,否则页面不会同步变化。

解决方案

下面提供两种可行方案,你可以根据需求选择:

方案一:用Bokeh Server运行Python回调

如果想保留Python逻辑,需要用Bokeh Server启动代码,步骤如下:

  1. 预先创建两个矩形渲染器,初始设置为隐藏;
  2. 在回调里根据复选框的激活状态切换对应矩形的visible属性;
  3. 用curdoc().add_root()替代show(),通过Bokeh Server启动服务。

修改后的代码:

from bokeh.io import curdoc
from bokeh.models import ColumnDataSource, HoverTool, CheckboxGroup, WidgetBox
from bokeh.plotting import figure
from bokeh.layouts import layout

# 模拟测试数据(你可以替换成自己的真实数据)
source = ColumnDataSource(data=dict(x=[10,20,30,40], y=[10,20,30,40]))
hover = HoverTool(tooltips=["(indep,dep)","($x,$y)"])
p = figure(plot_width=300, plot_height=300, tools=[hover], title="sample")

# 预先创建两个阴影矩形,初始隐藏
rect1 = p.quad(top=50.0, bottom=25.0, left=0.0, right=25.0, visible=False, fill_color='lightblue', fill_alpha=0.3)
rect2 = p.quad(top=25.0, bottom=0.0, left=25.0, right=50.0, visible=False, fill_color='lightgreen', fill_alpha=0.3)

checkbox_group = CheckboxGroup(labels=["select 1","select 2"], active=[])

def clicker(active):
    # 根据激活的复选框索引切换矩形可见性
    rect1.visible = 0 in active
    rect2.visible = 1 in active

checkbox_group.on_click(clicker)

circles = p.circle('x','y', source=source)
hover.renderers.append(circles)

L = layout([p, WidgetBox(checkbox_group)], sizing_mode='fixed')
curdoc().add_root(L)

运行方式:在终端执行bokeh serve --show your_script.py,浏览器会自动打开交互式页面。

方案二:用CustomJS做客户端回调(适合静态HTML)

如果想生成独立的静态HTML文件,不需要Bokeh Server,就用JavaScript回调:

  1. 预先创建两个矩形渲染器,初始隐藏;
  2. 编写JS逻辑,根据复选框状态切换矩形的可见性;
  3. 通过js_on_change绑定回调到复选框的active属性。

修改后的代码:

from bokeh.io import output_file, show
from bokeh.models import ColumnDataSource, HoverTool, CheckboxGroup, WidgetBox, CustomJS
from bokeh.plotting import figure
from bokeh.layouts import layout

# 模拟测试数据
source = ColumnDataSource(data=dict(x=[10,20,30,40], y=[10,20,30,40]))
hover = HoverTool(tooltips=["(indep,dep)","($x,$y)"])
p = figure(plot_width=300, plot_height=300, tools=[hover], title="sample")

# 预先创建两个阴影矩形,初始隐藏
rect1 = p.quad(top=50.0, bottom=25.0, left=0.0, right=25.0, visible=False, fill_color='lightblue', fill_alpha=0.3)
rect2 = p.quad(top=25.0, bottom=0.0, left=25.0, right=50.0, visible=False, fill_color='lightgreen', fill_alpha=0.3)

checkbox_group = CheckboxGroup(labels=["select 1","select 2"], active=[])

# 编写JavaScript回调逻辑
callback = CustomJS(args=dict(rect1=rect1, rect2=rect2), code="""
    const active = cb_obj.active;
    // 切换矩形可见性
    rect1.visible = active.includes(0);
    rect2.visible = active.includes(1);
""")

checkbox_group.js_on_change('active', callback)

circles = p.circle('x','y', source=source)
hover.renderers.append(circles)

output_file("test_scatter.html", mode="inline", title="sample scatter")
L = layout([p, WidgetBox(checkbox_group)], sizing_mode='fixed')
show(L)

直接运行脚本生成HTML文件,打开后点击复选框就能正常显示对应的阴影区域了。

关键要点总结
  • 静态HTML只能用CustomJS客户端回调,Python回调必须依赖Bokeh Server;
  • 推荐预先创建渲染器,通过切换visible属性控制显示/隐藏,而非每次点击新增元素;
  • 判断复选框状态时,用in检查索引是否在active列表中,避免索引越界错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:30:38