Python Bokeh TapTool的CustomJS回调调试求助
我帮你找到了问题所在,并且修正了代码。核心问题是回调绑定的位置不对,另外还有一个小的变量声明问题需要调整。
问题分析
- 回调绑定错误:你把
CustomJS绑定到了ColumnDataSource的callback属性,这个回调会在数据源发生变化时触发,而不是在点击TapTool时触发。我们需要把回调绑定到TapTool本身,这样点击事件触发时才会执行我们的高亮逻辑。 - 未声明变量:代码里的
attribute_value没有用var(或let/const)声明,会变成全局变量,可能导致意外的行为。
修正后的完整代码
# Import packages from bokeh.plotting import figure, show from bokeh.models import ColumnDataSource, CustomJS, HoverTool, TapTool # Create the data for the points x = [0, 1, 2, 3] y = [0, 1, 0, 1] ids = ['A','B','A','B'] data = {'x':x, 'y':y, 'id':ids} source = ColumnDataSource(data) # Add tools to the plot tap = TapTool() hover = HoverTool(tooltips=[("X", "@x"), ("Y", "@y"), ("ID", "@id")]) # Create a plotting figure p = figure(plot_width=400, plot_height=400, tools=[tap,hover]) # Code for the callback code = """ // Set column name to select similar glyphs var column = 'id'; // Get data from ColumnDataSource var data = source.data; // Get the index of the clicked item (TapTool gives the single clicked index) var clickedIndex = cb_obj.selected.indices[0]; // Array to store glyph-indices to highlight var select_inds = []; // Get the value of the column to find similar attributes/glyphs var attribute_value = data[column][clickedIndex]; // Iterate over all entries in the ColumnDataSource for (var i=0; i<data[column].length; ++i){ // Check if items have the same attribute if(data[column][i] === attribute_value){ // Add index to selected list select_inds.push(i); } } // Set selected glyphs in ColumnDataSource source.selected.indices = select_inds; // Save changes to ColumnDataSource source.change.emit(); """ # Create a CustomJS callback with the code and the data # 注意:这里我们传入cb_obj(即触发回调的TapTool对象) callback = CustomJS(args={'source': source}, code=code) # 把回调绑定到TapTool,而不是ColumnDataSource tap.callback = callback # Plots circles p.circle('x', 'y', source=source, size=25, color='blue', alpha=1, hover_color='black', hover_alpha=1, # 添加选中样式,让高亮更明显 selection_color='red', selection_alpha=1) # Show plot show(p)
关键修改说明
- 回调绑定位置:将
source.callback = callback改为tap.callback = callback,确保点击事件触发时执行回调逻辑。 - 获取点击索引:通过
cb_obj.selected.indices[0]获取点击的点的索引(cb_obj代表触发回调的TapTool实例),不需要判断长度,因为TapTool默认每次点击只会选中一个点。 - 变量声明:给
attribute_value添加var声明,避免全局变量污染。 - 添加选中样式:给
circleglyph添加selection_color和selection_alpha参数,让选中的点显示红色,高亮效果更直观。 - 严格相等判断:把
==改成===,遵循JS的最佳实践,避免隐式类型转换。
这样修改后,点击任意一个点,所有相同id的点都会被高亮显示(变成红色),完全符合你的需求。
内容的提问来源于stack exchange,提问作者Morris
相关产品推荐
相关产品推荐

