Component for bi-directional communication with bokeh

Many thanks @andfanilo .

Hey @blob123,

I whipped up something based on my previous answer.
Got it working working with some bokeh magic. Is it what you’re looking for ?

from streamlit_bokeh_events import streamlit_bokeh_events
from bokeh.plotting import figure
from bokeh.models import PointDrawTool, ColumnDataSource, CustomJS
import pandas as pd
import streamlit as st

def plot_and_move(df):
    p = figure(x_range=(0, 10), y_range=(0, 10), tools=[],
            title='Point Draw Tool')

    source = ColumnDataSource(df)

    renderer = p.scatter(x='x', y='y', source=source, size=10)

    draw_tool = PointDrawTool(renderers=[renderer])
    p.toolbar.active_tap = draw_tool

    source.js_on_change("data", CustomJS(
                new CustomEvent("DATA_CHANGED", {detail:})

    event_result = streamlit_bokeh_events(p, key="foo", events="DATA_CHANGED", refresh_on_update=False, debounce_time=0)

    if event_result:
        df_values = event_result.get("DATA_CHANGED")
        return pd.DataFrame(df_values, index=df_values.pop("index"))
        return df

df = pd.DataFrame({
        'x': [1, 5, 9], 'y': [1, 5, 9]


Hope it helps !


You’re becoming quite the Bokeh master there :stuck_out_tongue_winking_eye:


@ash2shukla, this is just awesome !

Many thanks !!

1 Like

Sorry @ash2shukla, by any chance is it possible to prevent the figure from creating new dots when clicking everywhere on the scatter plot ?

Sure, just pass add=False in the PointDrawTool constructor like this,

Change this

draw_tool = PointDrawTool(renderers=[renderer])

To this

draw_tool = PointDrawTool(renderers=[renderer], add=False)

Also check this for more customizations, eg custom icon in toolbar etc. — Bokeh 2.2.3 Documentation

Hope it helps ! :slight_smile:

It does !
Many thanks @ash2shukla.