交互式更改散景图中的字形

时间:2017-11-26 19:19:17

标签: python python-3.x bokeh

我正在尝试生成一个散景应用程序,允许用户更改绘图的字形。不幸的是,在调用下拉按钮的on_change()方法后,字形不会改变,尽管我能够以类似的方式更改轴标签。但是,在被调用函数之外更改plot.glyph可以正常工作。

from bokeh.layouts import layout
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Dropdown
from bokeh.plotting import figure
from bokeh.io import curdoc
from bokeh.models.markers import Cross, Circle

source=ColumnDataSource(dict(x=[1,2,3],y=[4,5,6]))

fig=figure()
plot=fig.circle(x='x', y='y',source=source)
fig.xaxis.axis_label='This is a label'

#this changes the glyphs from circle to cross
plot.glyph=Cross(x='x', y='y', size=20, line_color='firebrick',
fill_color='firebrick', line_alpha=0.8, fill_alpha=0.3)

def update_plot(attr,old,new):
    if dropdown.value=='cross':
        #this changes the axis label but not the glyphs
        fig.xaxis.axis_label='Label changed'
        plot.glyph=Cross(x='x', y='y', size=20, line_color='firebrick',
        fill_color='firebrick', line_alpha=0.8, fill_alpha=0.3)
    elif dropdown.value=='circle':
        #this also only changes the axis label but not the glyphs
        fig.xaxis.axis_label='Label changed again'
        plot.glyph=Circle(x='x', y='y', size=20, line_color='firebrick',
        fill_color='firebrick', line_alpha=0.8, fill_alpha=0.3)

menu=[('Circle','circle'),('Cross', 'cross')]
dropdown=Dropdown(label="Select marker", menu=menu, value='circle')
dropdown.on_change('value', update_plot)

lay_out=layout([fig, dropdown])

curdoc().add_root(lay_out)

1 个答案:

答案 0 :(得分:2)

我不确定你的方法不起作用的确切原因,但是这个方法有效:

from bokeh.io import curdoc
from bokeh.layouts import layout
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Dropdown
from bokeh.plotting import figure

source = ColumnDataSource(dict(x=[1, 2, 3], y=[4, 5, 6]))

plot = figure()

renderers = {rn: getattr(plot, rn)(x='x', y='y', source=source,
                                   **extra, visible=False)
             for rn, extra in [('circle', dict(size=10)),
                               ('line', dict()),
                               ('cross', dict(size=10)),
                               ('triangle', dict(size=15))]}


def label_fn(item):
    return 'Select marker ({})'.format(item)


menu = [('No renderer', None)]
menu.extend((rn.capitalize(), rn) for rn in renderers)

dropdown = Dropdown(label=label_fn(None), menu=menu, value=None)


def update_plot(attr, old, new):
    dropdown.label = label_fn(new)
    for renderer_name, renderer in renderers.items():
        renderer.visible = (renderer_name == new)


dropdown.on_change('value', update_plot)

lay_out = layout([plot, dropdown])

curdoc().add_root(lay_out)

基本上,我事先创建了所有必需的渲染器,然后只需切换每个渲染器的visible标志。

另外,请注意正确的术语。您所谓的情节,实际上不是情节而是字形渲染器。情节和人物基本相同。