☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

Callback on Point Drag using on_event(Pan, callback) vs on_change('indices', callback)

Community Support
eppoch
eppoch

Hello bokeh Comunity,

This is my first post, I’m very new to Python and Bokeh. This is an amazing tools for making an interactive dashboard using python. However I need a very specific tools for interaction that I can’t find anywhere in internet.

I need to have a callback action that occur at the end PointDrawTools.

I made script that execute callback using PointDrawTool using two methods that resulting similar result, but not that I want:

  1. Callback using on_change('indices', callback)
    This method allow me to callback on the beginning data source change. In relation with Point Drag, it occur on start of Point Drag.

  2. Callback using on_event(Pan, callback)
    This method allow me to callback upon Pan on figure and at the end Point Drag. But i need the callback executed at the end of Point Drag only, not during Panning of Figure.

1st method have a little bit of problem, I need to data synchronization at the end of Point Drag.

2nd methods work just fine, it callbacks at the end Point Drag and figure panning. I need to have data synchronize only at the end Point Drag only (or during Point Drag only), not during Panning on figure.

Is there any way for me to have Callback at the end of Point Drag?

here is the minimal code that I write:

from bokeh.models import ColumnDataSource, Column, Row, PointDrawTool, Div, CustomJS
from bokeh.models.widgets import DataTable, TableColumn
from bokeh.io import curdoc
from bokeh.plotting import figure
from bokeh.events import PanEnd

def callback_source_change(attr, old, new):
    data3.data = data12.data


def callback_pan():
    data3.data = data12.data


xa = [1, 3, 3, 4, 5, 1]
ya = [2, 6, 4, 5, 8, 4]

ca = ['red'] * 3 + ['green'] * 3
data12 = ColumnDataSource({'xa': xa, 'ya': ya, 'ca': ca})
data3 = ColumnDataSource({'xa': xa, 'ya': ya, 'ca': ca})

p1 = figure(title="Callback using source.selected.on_change('indices', callback)")
r1 = p1.circle(x='xa', y='ya', color='ca', size=10, source=data12)

# 1 st method
p1.add_tools(PointDrawTool(renderers=[r1], add=False))
data12.selected.on_change('indices', callback_source_change)

# 2 st method
p2 = figure(title="Callback using figure.on_event(Pan, callback)")
r2 = p2.circle(x='xa', y='ya', color='ca', size=10, source=data12)
p2.add_tools(PointDrawTool(renderers=[r2], add=False))
p2.on_event(PanEnd, callback_pan)

# Target Result
p3 = figure(title="Callback Result")
p3.circle(x='xa', y='ya', color='ca', source=data3)

p1.x_range = p2.x_range = p3.x_range
p1.y_range = p2.y_range = p3.y_range

columns = [TableColumn(field="xa", title="xa"),
           TableColumn(field="ya", title="ya"),
           TableColumn(field="ca", title="ca")]

data_table12 = DataTable(source=data12, columns=columns)
data_table3 = DataTable(source=data3, columns=columns)

p = Row(Column(p1, data_table12),
        Column(p2, data_table12),
        Column(p3, data_table3))

curdoc().add_root(p)

Note:
on 1st method, the target data source not immediately updated. It updated on on second trial on start of dragging.

on 2 method, call back also occur during figure Panning (see terminal output)

Best regards,

⌁   Link to post
p-himik
p-himik

The issue here is that even if you have the tool activated and just try to drag the plot itself (i.e. something that’s a no-op), you will still get PanEnd. There seems to be no way to check if an actual action has been done.

⌁   Link to post
Bryan
Bryan

Ah, fair enough. It may just be a case of something that would require new development, then. E.g. perhaps gesture tools specifically could fire a new GestureDone event that could include some extra context about what happened. Seems a GitHub issue would be an appropriate next step.

⌁   Link to post

End of archived discussion · Replies are disabled