如何通过散景图中的选择更改来替换面板的一部分?
How can I replace part of a panel via a selection change in a Bokeh figure?
通常,我可以通过 pop
和 insert
替换面板的一部分,它们会自动更新任何现有面板。但是,如果这些是由散景 selected.on_change
回调触发的,
现有面板不会更新。
例如,运行在 JupyterLab 中执行以下操作
from bokeh.plotting import figure
from bokeh.sampledata.iris import flowers
from bokeh.models import ColumnDataSource
import panel as pn
pn.extension()
def create_figure():
src = ColumnDataSource(flowers)
p = figure(height=200, width=200, tools='box_select')
p.circle("petal_length", "petal_width", source=src)
return p
pnl = pn.panel(pn.Row(create_figure, create_figure))
pnl
当我 运行 在下一个单元格中输入以下内容时,显示的面板将按预期更新:
pnl.pop(0)
pnl.insert(0, figure)
但是,如果我在列数据源的 selection 发生变化时通过回调执行相同的操作,面板不会更新,因为我在图中 select 数据点:
def replace_plot(attr, old, new):
pnl.objects.pop(0)
pnl.objects.insert(0, figure)
def create_figure():
src = ColumnDataSource(flowers)
p = figure(height=200, width=200, tools='box_select')
p.circle("petal_length", "petal_width", source=src)
src.selected.on_change('indices', replace_plot)
return p
pnl = pn.panel(pn.Row(create_figure, create_figure))
pnl
有效的方法是用新列表替换整个 pnl.objects
:
def replace_plot(attr, old, new):
pnl.objects = [figure]
奇怪的是,这仅在我调用 pnl.show()
以在新的浏览器选项卡中显示面板时有效,在笔记本中我需要在新的单元格中再次显示面板以查看更新。我尝试通过索引替换 objects
列表中的单个项目,但这与 pop
和 insert
相同,面板没有自动更新。
有没有办法通过 selected.on_change
回调替换面板的一部分并让它自动刷新(最好在笔记本内部,但通过 show
也可以)?
版本:
-----
bokeh 2.0.1
pandas 1.0.3
panel 0.9.5
-----
IPython 6.5.0
jupyter_client 5.2.3
jupyter_core 4.6.3
jupyterlab 2.1.0
notebook 5.6.0
-----
Python 3.7.6 | packaged by conda-forge | (default, Mar 23 2020, 23:03:20) [GCC 7.3.0]
Linux-5.6.13-arch1-1-x86_64-with-arch
4 logical CPU cores
-----
Session information updated at 2020-05-21 18:38
原来这是面板中的错误,现在正在 https://github.com/holoviz/panel/issues/1368 进行跟踪。目前,以下代码片段可以解决该问题:
from panel.io.notebook import push
def replace_plot(attr, old, new):
for ref in pnl._models:
_, _, doc, comm = pn.state._views[ref]
doc.hold()
pnl[0] = 1
push(doc, comm)
for ref in pnl._models:
_, _, doc, comm = pn.state._views[ref]
doc.unhold()
通常,我可以通过 pop
和 insert
替换面板的一部分,它们会自动更新任何现有面板。但是,如果这些是由散景 selected.on_change
回调触发的,
现有面板不会更新。
例如,运行在 JupyterLab 中执行以下操作
from bokeh.plotting import figure
from bokeh.sampledata.iris import flowers
from bokeh.models import ColumnDataSource
import panel as pn
pn.extension()
def create_figure():
src = ColumnDataSource(flowers)
p = figure(height=200, width=200, tools='box_select')
p.circle("petal_length", "petal_width", source=src)
return p
pnl = pn.panel(pn.Row(create_figure, create_figure))
pnl
当我 运行 在下一个单元格中输入以下内容时,显示的面板将按预期更新:
pnl.pop(0)
pnl.insert(0, figure)
但是,如果我在列数据源的 selection 发生变化时通过回调执行相同的操作,面板不会更新,因为我在图中 select 数据点:
def replace_plot(attr, old, new):
pnl.objects.pop(0)
pnl.objects.insert(0, figure)
def create_figure():
src = ColumnDataSource(flowers)
p = figure(height=200, width=200, tools='box_select')
p.circle("petal_length", "petal_width", source=src)
src.selected.on_change('indices', replace_plot)
return p
pnl = pn.panel(pn.Row(create_figure, create_figure))
pnl
有效的方法是用新列表替换整个 pnl.objects
:
def replace_plot(attr, old, new):
pnl.objects = [figure]
奇怪的是,这仅在我调用 pnl.show()
以在新的浏览器选项卡中显示面板时有效,在笔记本中我需要在新的单元格中再次显示面板以查看更新。我尝试通过索引替换 objects
列表中的单个项目,但这与 pop
和 insert
相同,面板没有自动更新。
有没有办法通过 selected.on_change
回调替换面板的一部分并让它自动刷新(最好在笔记本内部,但通过 show
也可以)?
版本:
-----
bokeh 2.0.1
pandas 1.0.3
panel 0.9.5
-----
IPython 6.5.0
jupyter_client 5.2.3
jupyter_core 4.6.3
jupyterlab 2.1.0
notebook 5.6.0
-----
Python 3.7.6 | packaged by conda-forge | (default, Mar 23 2020, 23:03:20) [GCC 7.3.0]
Linux-5.6.13-arch1-1-x86_64-with-arch
4 logical CPU cores
-----
Session information updated at 2020-05-21 18:38
原来这是面板中的错误,现在正在 https://github.com/holoviz/panel/issues/1368 进行跟踪。目前,以下代码片段可以解决该问题:
from panel.io.notebook import push
def replace_plot(attr, old, new):
for ref in pnl._models:
_, _, doc, comm = pn.state._views[ref]
doc.hold()
pnl[0] = 1
push(doc, comm)
for ref in pnl._models:
_, _, doc, comm = pn.state._views[ref]
doc.unhold()