Karel Marik
Karel Marik

Reputation: 1003

How to protect glyph from being selected and changed by the TapTool?

I need to setup single bokeh figure with multiple glyphs and just subset of glyphs should be selectable (i.e. action is triggered after mouse click on certain glyph). After many trials and errors I found a way to set nonselection_glyph property of glyph to None (see code below). Is it the most efficient way to set a glyph unselectable (or disable changes after selection)?

from bokeh.plotting import figure, curdoc
from bokeh.layouts import column
from bokeh.models import ColumnDataSource

TOOLS = "tap"
p = figure(title="Some Figure", tools=TOOLS)

patches_source = ColumnDataSource(dict(x=[[1, 3, 2], [3, 4, 6, 6]], y=[[2, 1, 4], [4, 7, 8, 5]], alphas = [0.8, 0.3], colors=["firebrick", "navy"], name=['A', 'B']))
circles_source = ColumnDataSource(dict(x=[5, 7, 6], y=[2, 1, 4], alphas = [1.0, 1.0, 1.0], colors=["firebrick", "navy", "greeb"], name=['A', 'B', 'C']))

cglyph = p.circle(x='x', y='y', source=circles_source, size=25, line_width=2, alpha = 'alphas', color='colors')
pglyph = p.patches(xs='x', ys='y', source=patches_source, line_width=2, alpha = 'alphas', color='colors')
pglyph.nonselection_glyph = None #makes glyph invariant on selection


def callback_fcn(attr, old, new):
    if new['1d']['indices']:
        print('Newly selected: {}'.format(new['1d']['indices'][-1]))
    else:
        print('Nothing selected')
    print("{} - {} - {}".format(attr, old, new))

cglyph.data_source.on_change('selected',callback_fcn)
curdoc().add_root(column(p))

Upvotes: 5

Views: 752

Answers (1)

ChesuCR
ChesuCR

Reputation: 9630

You can create the TapTool manually and set the renderers attribute, which will be the list of renderers where you want to use the tool:

from bokeh.plotting import figure, curdoc
from bokeh.layouts import column
from bokeh.models import ColumnDataSource
from bokeh.models.tools import TapTool

p = figure(title="Some Figure", tools='')

patches_source = ColumnDataSource(dict(
    x=[[1, 3, 2], [3, 4, 6, 6]], y=[[2, 1, 4], [4, 7, 8, 5]],
    alphas = [0.8, 0.3], colors=["firebrick", "navy"],
    name=['A', 'B']
))
circles_source = ColumnDataSource(dict(
    x=[5, 7, 6], y=[2, 1, 4],
    alphas=[1.0, 1.0, 1.0], colors=["firebrick", "navy", "greeb"],
    name=['A', 'B', 'C']
))
cglyph = p.circle(
    x='x', y='y', source=circles_source, size=25,
    line_width=2, alpha='alphas', color='colors'
)
pglyph = p.patches(
    xs='x', ys='y', source=patches_source, 
    line_width=2, alpha = 'alphas', color='colors'
)

tap = TapTool(renderers=[cglyph])
tools = (tap)
p.add_tools(*tools)

def callback_fcn(attr, old, new):
    print("{} - {} - {}".format(attr, old, new))

cglyph.data_source.selected.on_change('indices',callback_fcn)
curdoc().add_root(column(p))

Note: Alternatively you can ser a list of renderer names

Upvotes: 3

Related Questions