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

Bokeh技术问题:如何在不同标签页中复用并同步同一组件?

问题分析与解决方案

问题根源

你遇到的核心问题是:filter1和filter2实际上是同一个组件实例。

看你的代码,init()函数创建了全局的multiselect和input_box,然后Filter类的__init__直接复用这两个全局对象,生成的widgetbox自然也是同一个实例。Bokeh不允许同一个组件实例被同时添加到多个容器(比如不同的Panel)中,所以当你尝试把它们放进Tabs时,Bokeh无法正确渲染标签页结构,只会把重复的组件直接显示在页面上。

解决方案:让每个筛选器拥有独立组件,同时同步状态

我们需要修改代码,让每个Filter实例创建自己的TextInput和MultiSelect组件,然后通过共享的回调逻辑来实现两个筛选器之间的状态同步。

修改后的完整代码如下:

from bokeh.io import curdoc
from bokeh.layouts import widgetbox, row, layout
from bokeh.models import TextInput, MultiSelect
from bokeh.models.widgets import Panel, Tabs
import pandas as pd
from functools import partial

# 共享的数据源
df = pd.DataFrame(["apples", "oranges", "grapes"], columns=["fruits"])

def update(filter_instances, widget_name, attr, old, new):
    """共享的回调函数,更新所有筛选器的MultiSelect选项"""
    if widget_name == 'input':
        # 根据输入文本过滤数据
        filtered_fruits = sorted(list(df[df['fruits'].str.contains(new)]['fruits']))
        # 更新所有筛选器的MultiSelect选项
        for filter_inst in filter_instances:
            filter_inst.multiselect.options = filtered_fruits

class Filter:
    def __init__(self, filter_instances):
        # 每个Filter实例创建自己的独立组件
        self.input_box = TextInput(title='Input', name='input', value='Enter your choice')
        self.multiselect = MultiSelect(title='Multiselect', name='multiselect', value=[], options=list(df["fruits"]))
        # 绑定回调,传入所有筛选器实例以便同步更新
        self.input_box.on_change('value', partial(update, filter_instances, self.input_box.name))
        self.widget = widgetbox(self.input_box, self.multiselect)

# 创建两个筛选器实例,互相传入以便同步
filter_instances = []
filter1 = Filter(filter_instances)
filter_instances.append(filter1)
filter2 = Filter(filter_instances)
filter_instances.append(filter2)

# 构建标签页
p1 = Panel(child=filter1.widget, title="Panel 1")
p2 = Panel(child=filter2.widget, title="Panel 2")
tabs = Tabs(tabs=[p1, p2])

curdoc().add_root(layout(tabs))

关键修改点说明

  • 去掉全局变量:每个Filter实例现在会初始化自己的TextInput和MultiSelect,确保两个筛选器是完全独立的组件实例,能正常被Tabs渲染。
  • 共享回调逻辑:update函数接收所有筛选器实例的列表,当任何一个输入框的内容变化时,会更新所有筛选器的MultiSelect选项,实现状态同步。
  • 正确构建Tabs:现在filter1.widget和filter2.widget是两个不同的widgetbox,分别放入不同的Panel中,Tabs就能正常渲染标签页结构了。

这样修改后,你就能看到正常的标签页,并且在任意一个标签页的输入框中输入文本,两个标签页的MultiSelect选项都会同步更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:02:27