Streamlit Bokeh 事件回调以获取点击值

问题描述 投票:0回答:1

当用户单击散点图中的点时,我试图从单击中获取值。 下面显示了该图,但最后没有显示字典的值。

由于它是streamlit,所以使用bokeh==2.4.3

import streamlit as st
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, CustomJS

# Create a Streamlit web app
st.title("Interactive Scatter Plot")

# Create some example data
data = {
    "x": [1, 2, 3, 4, 5],
    "y": [5, 4, 3, 2, 1],
}

# Create a Bokeh figure and add a scatter plot
p = figure(title="Click on a dot", tools="tap,reset")
source = ColumnDataSource(data=data)
scatter = p.circle("x", "y", size=20, source=source)

# Create a JavaScript callback function
callback_code = """
    const selected_indices = cb_obj.indices;
    if (selected_indices.length > 0) {
        const selected_index = selected_indices[0];
        const x_value = source.data['x'][selected_index];
        const y_value = source.data['y'][selected_index];
        
        clicked_data.x = x_value;
        clicked_data.y = y_value;
    }
"""
clicked_data = {"x": None, "y": None}
callback = CustomJS(
    args={"source": source, "clicked_data": clicked_data}, code=callback_code
)

# Attach the JavaScript callback to the scatter plot
scatter.js_on_event("tap", callback)


# Display the Bokeh plot in Streamlit
st.bokeh_chart(p, use_container_width=True)

st.write(clicked_data)
callback bokeh streamlit
1个回答
0
投票

您想要做的是从前端到后端获取一个值,为此您需要一个 webhook 或 websocket。它与 Bokeh/streamlit 无关。

如果您只需要更新 UI 中的某些组件,在 Bokeh 中创建所有组件,在回调中更改它,然后将整个 UI 发送到 Streamlit。

在下面的代码中,我根据所选点更新

x, y
-

from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, CustomJS, Div
from bokeh.layouts import Column

# Create a Streamlit web app
st.title("Interactive Scatter Plot")

# Create some example data
data = {
    "x": [1, 2, 3, 4, 5],
    "y": [5, 4, 3, 2, 1],
}

clicked_data = {"x": None, "y": None}

# Create a Bokeh figure and add a scatter plot
p = figure(title="Click on a dot", tools="tap,reset")
source = ColumnDataSource(data=data)
scatter = p.circle("x", "y", size=20, source=source)
div = Div(text  = str(clicked_data))

c = Column(p, div)


# Create a JavaScript callback function
callback_code = """
    const selected_indices = cb_obj.indices;
    if (selected_indices.length > 0) {
        const selected_index = selected_indices[0];
        const x_value = source.data['x'][selected_index];
        const y_value = source.data['y'][selected_index];
        
        clicked_data.x = x_value;
        clicked_data.y = y_value;
        div.text = '{"x" : ' + x_value + ',  "y" : ' + y_value +'}';
    }
    else{
        div.text = '{"x" : ' + 'None' + ',  "y" : ' + 'None' +'}';
    }
 
    div.change.emit();
"""
callback = CustomJS(
    args={"source": source, "clicked_data": clicked_data, "div" : div}, code=callback_code
)

# Attach the JavaScript callback to the scatter plot
scatter.data_source.selected.js_on_change('indices', callback)


# Display the Bokeh plot in Streamlit
st.bokeh_chart(c, use_container_width=True)

我添加了一个带有 x 和 y 值的 div,并且我正在回调函数中根据我的选择更改 div 的文本。如果您想使用此选择来绘制/显示任何内容,请在散景本身中创建该 UI,并将完整的 UI(通过布局配置)传递给 Streamlit。

© www.soinside.com 2019 - 2024. All rights reserved.