Not able to implement hover callback in bokeh on streamlit

Hello @ElisonSherton @ehknight

The long reason is here: Restrict Download of Images & Videos on Streamlit App - #2 by andfanilo

The Streamlit server serves static objects from its installation directory only, rather than your project workspace. You will need to copy/paste your png files to this directory so Bokeh refers them correctly.

The following worked on my side

import streamlit as st
import pathlib
import pandas as pd
import shutil
from bokeh.plotting import figure
from bokeh.models.tools import HoverTool
from bokeh.models import ColumnDataSource


# create a png_hack folder in Streamlit's static directory
STREAMLIT_STATIC_PATH = pathlib.Path(st.__path__[0]) / "static"
PNG_PATH = STREAMLIT_STATIC_PATH / "png_hack"

if not PNG_PATH.is_dir():
    PNG_PATH.mkdir()

# copy your PNG files to the static directory
for p in ["lol.png", "lol2.png", "lol12.png"]:
    if not (PNG_PATH / p).exists():
        shutil.copy("/workspace/" + p, PNG_PATH / p)

p = figure(
    plot_width=1500,
    plot_height=900,
    title=f"Demo",
    x_axis_label="X",
    y_axis_label="Y",
)


# static files are referred relative to the static directory now
df = pd.DataFrame(
    {
        "x": [1, 1, 2],
        "y": [1, 2, 1],
        "ImgName": [
            "png_hack/lol.png",
            "png_hack/lol2.png",
            "png_hack/lol12.png",
        ],
    }
)


p.scatter(
    y="y",
    x="x",
    source=ColumnDataSource(df),
    size=10,
)

hover = HoverTool()
hover.tooltips = """
    <div>
        <h2>Figure</h2>
        <div>
            <img src="@ImgName" alt="@ImgName" style="border:2px solid black; border-radius:20%" width="150"/>
        </div>
    </div>
"""

p.add_tools(hover)

st.title("Visualization")
st.bokeh_chart(p, use_container_width=True)

Now you will probably need to clean this folder regularly, and note that any Streamlit reinstall will purge it :wink:

Have a nice day,
Fanilo

3 Likes