Bokeh Server:如何在回调函数中批量选中同组Patch元素
解决Bokeh点击Patch高亮同组所有元素的问题
我来帮你搞定这个Bokeh的选择高亮问题!你现在的代码里,直接赋值source.selected.indices没法正确触发Bokeh的视图更新,所以同组Patch没被高亮。下面是修复后的完整代码,以及关键的修改说明:
问题根源
你遇到的核心问题是:直接修改source.selected.indices这个属性时,Bokeh的属性变更检测机制没被触发——因为这是对对象属性的直接赋值,不是通过Bokeh推荐的方法更新的,所以图表不会同步更新选中状态。另外,你用df['id']来获取组索引的方式虽然当前数据没问题,但不够健壮,最好直接用数据源的行索引来定位元素。
修复后的完整代码
import os from bokeh.models import ColumnDataSource, Patches from bokeh.plotting import figure from bokeh.layouts import row from bokeh.io import output_file, curdoc import pandas as pd x = [[1,2,4], [3,5,6], [7,9,7], [5,7,6]] y = [[4,2,1], [6,5,8], [3,9,6], [2,2,1]] group = ['A', 'A', 'B', 'B'] id = [0,1,2,3] df = pd.DataFrame(data=dict(x=x, y=y, group=group, id=id)) source = ColumnDataSource(df) p = figure(tools="tap") renderer = p.patches('x', 'y', source=source) # 设置选中后的样式 selected_patches = Patches(fill_color="#a6cee3") renderer.selection_glyph = selected_patches # 点击事件处理函数 def my_tap_handler(attr, old, new): # 先判断是否有点击到元素,避免空索引报错 if not new['1d']['indices']: return # 获取点击元素的组名 clicked_idx = new['1d']['indices'][0] group_name = source.data['group'][clicked_idx] # 获取同组所有元素的行索引(更可靠的方式) group_indices = df.index[df['group'] == group_name].tolist() # 使用update方法更新选中状态,触发Bokeh的视图更新 source.selected.update(indices=group_indices) print("当前选中索引:", source.selected.indices) # 绑定选中变更事件 renderer.data_source.on_change("selected", my_tap_handler) # 添加到文档 curdoc().add_root(row(p, width=800))
关键修改说明
- 用
source.selected.update()替代直接赋值:这个方法会主动触发Bokeh的属性变更通知,让图表立刻更新选中的高亮状态,这是解决问题的核心。 - 改用行索引获取组元素:通过
df.index[df['group'] == group_name]直接拿到数据源的行索引,不再依赖id列和索引的一致性,代码更健壮,后续数据有变化也不容易出错。 - 增加空值判断:先检查
new['1d']['indices']是否为空,防止用户点击图表空白区域时出现索引越界的错误。
这样修改后,你点击任意一个Patch,同组的所有Patch都会立刻被高亮选中,完全符合你的需求。
内容的提问来源于stack exchange,提问作者otwtm
相关产品推荐
相关产品推荐

