Bokeh:如何实现CustomJS按钮全量清除DataTable选中状态?
问题分析与解决
问题原因
当使用CDSView过滤DataTable时,Bokeh的DataTable组件会为每个不同的视图维护独立的选中状态缓存。切换滑块(切换视图)时,DataTable会将当前视图对应的缓存选中状态同步回ColumnDataSource的selected.indices中。
你的清除按钮仅清空了当前视图对应的CDS选中索引,但其他视图的选中缓存依然存在。当切回原视图时,DataTable会把缓存的选中状态重新写入CDS,导致之前的选中状态“复活”。
解决方案
修改清除按钮的CustomJS,不仅清空ColumnDataSource的选中索引,还要主动触发DataTable的状态更新,同时确保所有视图的选中缓存被清空。具体做法是将data_table传入CustomJS,直接操作其选中状态并触发变更事件。
修改后的完整代码
import numpy as np import pandas as pd from bokeh.io import show from bokeh.layouts import column from bokeh.plotting import figure from bokeh.models import ColumnDataSource, CDSView, CustomJS, CustomJSFilter, Slider, TableColumn, DataTable, SelectEditor, Button x = np.arange(0, 10, 0.1) dfs = [] tstep = 1 ts = range(0, 100, tstep) for t in ts: y = x**(t/50.) dfs.append(pd.DataFrame({"x": x, "y": y, "t": t})) df = pd.concat(dfs) cds = ColumnDataSource(df) t_slider = Slider(start=ts[0], end=ts[-1], step=tstep, value=0) # Callback to notify downstream objects of data change change_callback = CustomJS(args=dict(source=cds), code=""" source.change.emit(); """) t_slider.js_on_change('value', change_callback) # JS filter to select data rows matching t value on slider js_filter = CustomJSFilter(args=dict(slider=t_slider), code=""" const indices = []; // iterate through rows of data source and see if each satisfies some constraint for (let i = 0; i < source.get_length(); i++){ if (source.data['t'][i] == slider.value){ indices.push(true); } else { indices.push(false); } } return indices; """) # Use the filter in a view view = CDSView(filter=js_filter) # Add table to use for selecting data columns = [ TableColumn(field="x", title="x", editor=SelectEditor()), TableColumn(field="y", title="y", editor=SelectEditor()), ] data_table = DataTable(source=cds, columns=columns, selectable="checkbox", width=800, view=view) p = figure(x_range=(0,10), y_range=(0,100)) p.scatter(x='x', y='y', source=cds, view=view) # Button to clear selection - 修改后的CustomJS clear_button = Button(label="Clear selection", button_type="success") custom_js_button = CustomJS(args=dict(source=cds, table=data_table), code=""" // 清空CDS的选中索引 source.selected.indices = []; // 清空DataTable的选中状态缓存 table.selected.indices = []; // 触发变更事件,通知所有关联组件更新 source.change.emit(); table.change.emit(); """) clear_button.js_on_event("button_click", custom_js_button) layout = column(p, t_slider, data_table, clear_button) show(layout)
关键修改点
- 将
data_table作为参数传入CustomJS - 同时清空
source.selected.indices和table.selected.indices - 调用
source.change.emit()和table.change.emit()强制触发所有组件的状态更新,确保缓存的选中状态被彻底清除
内容的提问来源于stack exchange,提问作者Ben Farmer
相关产品推荐
相关产品推荐

