Bokeh CustomJS实现Jupyter交互式散点图无更新问题求助
问题修复与Bokeh交互式核心要点
你的代码存在两个关键问题导致滑块拖动后图表无更新,以下是修复方案及核心知识点:
代码修复
错误原因
- 滑块值获取错误:你将
f1和f2都赋值为cb_obj.value,但cb_obj仅代表当前触发事件的滑块(比如拖动slider1时,cb_obj就是slider1),这会导致两个变量取同一个滑块的值,无法正确获取另一个滑块的当前值。 - 未显式触发数据源更新:虽然重新赋值
source.data理论上会触发更新,但部分场景下需要显式通知Bokeh数据源已变化。
修复后的代码
from bokeh.models import ColumnDataSource, Slider, CustomJS from bokeh.plotting import figure, show from bokeh.layouts import column source = ColumnDataSource(data=dict(x=[1,0,1], y=[0,1,1])) plot = figure(width=400, height=400) plot.circle('x', 'y', source=source, line_width=3, line_alpha=0.6) slider1 = Slider(start=0.1, end=6, value=1, step=.1, title="Escalar 1") slider2 = Slider(start=0.1, end=6, value=1, step=.1, title="Escalar 2") update_tamanho = CustomJS(args=dict(source=source, slider1=slider1, slider2=slider2), code=""" // 直接从传入的滑块对象获取当前值,不依赖cb_obj const f1 = slider1.value; const f2 = slider2.value; const x = source.data.x; const y = source.data.y; // 修改指定点的坐标 x[0] = f1; x[2] = f1; y[1] = f2; y[2] = f2; // 显式通知Bokeh数据源更新,触发图表重绘 source.change.emit(); """) slider2.js_on_change('value', update_tamanho) slider1.js_on_change('value', update_tamanho) show(column(slider1, slider2, plot))
Bokeh交互式图表核心要点
- ColumnDataSource是交互核心:所有可交互的图表元素都要绑定到ColumnDataSource,它是Python与JS端数据同步的桥梁,修改数据源即可联动更新图表。
- CustomJS的参数与cb_obj:
args用于将Python端的对象(数据源、控件等)传递到JS代码,在JS中可直接访问对象属性(如value)。cb_obj仅代表当前触发事件的控件,适合单个控件控制单一参数的场景,多控件联动时直接从传入的控件对象取值更可靠。
- 事件绑定规则:
- 纯前端交互用
js_on_change绑定CustomJS,无需后端,适合Jupyter Notebook静态展示。 - 需要后端逻辑处理时,用
on_change绑定Python回调,但必须启动Bokeh服务器。
- 纯前端交互用
- JS端数据源更新:修改数据源数组后,需调用
source.change.emit()显式触发更新;优先修改数组元素而非替换整个数组,性能更优。 - 两种交互模式:
- 纯前端模式:适合简单交互,无需服务器,静态页面即可运行。
- 后端模式(Bokeh Server):支持复杂Python逻辑处理,实现双向实时数据同步。
内容的提问来源于stack exchange,提问作者Eternal Vigilance
相关产品推荐
相关产品推荐

