Warm tip: This article is reproduced from stackoverflow.com, please click
bokeh ipywidgets python-3.x updates

How can the `_property_values` of an element of a bokeh `figure.renderers` be changed directly?

发布于 2020-05-06 17:23:17

How can the _property_values of an element of a bokeh figure.renderers be changed directly? I learned that the lements of renderers have an id, so I expect to do something like renderers['12345']. But as it is a list (a PropertyValueList to be more precise), this doesn't work. Instead, the only solution I found is to iterate over the list, storing the correct element in a new pointer (?), modifying the pointer and thus modifying the original element.

Here is my toy example where a vertical line in a histogram is updated based on some widget's value:

import hvplot.pandas
import ipywidgets as widgets
import numpy as np
from bokeh.io import push_notebook, show, output_notebook
from bokeh.models import Span
from bokeh.plotting import figure

%matplotlib inline

hist, edges = np.histogram([1, 2, 2])

p = figure()
r = p.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:])
vline = Span(location=0, dimension='height')
p.renderers.extend([vline])

def update_hist(x):    
    myspan = [x for x in p.renderers if x.id==vline.id][0]
    myspan._property_values['location'] = x
    show(p, notebook_handle=True)

widgets.interact(update_hist, x = widgets.FloatSlider(min=1, max=2))
Questioner
Qaswed
Viewed
49
Qaswed 2020-02-21 17:00

Bigreddot pointed me into the right direction: I don't have to update p directly, but the elements used to generate p (here the Span). By this I found the this question where the code bears the solution: update vline.location.

Full code:

import hvplot.pandas
import ipywidgets as widgets
import numpy as np
from bokeh.io import push_notebook, show, output_notebook
from bokeh.models import Span
from bokeh.plotting import figure

%matplotlib inline

hist, edges = np.histogram([1, 2, 2])

p = figure()
r = p.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:])
vline = Span(location=0, dimension='height')
p.renderers.extend([vline])
show(p, notebook_handle=True)

def update_hist(x):    
    vline.location = x
    push_notebook()

widgets.interact(update_hist, x = widgets.FloatSlider(min=1, max=2, step = 0.01))

As a Python beginner, I still often oversee, that Python does not have variables. So we can change an element x by changing y.

x = ['alice']
y = x
y[0] = 'bob'
x  # is now ['bob] too