this is my first experience with bokeh. I am using windows 7, Pycharm as IDE, and python 3.7. I am trying to make a form with 4 TextInput to get values for mean, variance, number of rows and number of columns from user, with a Button that when clicked generate a dataframe of random numbers with normal distribution with input mean and variance with the defined input size. I have made the form by following the adding widgets link, and have written the dataframe generator. But I have difficulty binding it to the button. In order to make sure that I am correctly handling the event, I have added another TextInput just to show the value of mean TextInput when the button is clicked. The code is as follows:
from bokeh.models.widgets import TextInput, Button, Div
from bokeh.layouts import layout, column, row
from bokeh.io import curdoc ## to assign callback to widget
from bokeh import events ## for event handling
from bokeh.models import CustomJS
import numpy as np
import pandas as pd
text_input_mean = TextInput(value="0.0", title="Enter mean:")
text_input_vaiance = TextInput(value="0.0", title="Enter variance:")
text_input_rows = TextInput(value="5", title="Enter num rows:")
text_input_columns = TextInput(value="5", title="Enter num columns:")
button = Button(label = "Generate Dataframe", button_type = "success")
text_output = TextInput(title = 'Python result is shown here: ')
div = Div(text="""Making a form with bokeh mainly to handle events.""",
width=500, height=50)
layout = column(div, row(text_input_mean, text_input_vaiance), row(text_input_rows, text_input_columns),
button, text_output)
show(layout)
## Events with no attributes
# button.js_on_event(events.ButtonClick, button_click_handler) # Button click
def my_text_input_handler(attr, old, new):
print("Previous label: " + old)
print("Updated label: " + new)
text_input_mean.on_change("value", my_text_input_handler)
def button_click_handler():
text_output.__setattr__('value', str(text_input_mean.value))
#text_output.value = str(text_input_mean.value)
button.on_click(button_click_handler)
# button.on_click(generate_normal_df)
# curdoc().add_root(layout)
def generate_normal_df(mean, var, x, y):
mean = text_input_mean.value
variance = text_input_vaiance.value
row_num = x
col_num = y
return pd.DataFrame(np.random.normal(loc = mean, scale = variance, size=(row_num, col_num)))
When the button is clicked nothing happens! I looked into console as well, but there is nothing there either. I have used the method "my_text_input_handler" in the same link to see if I change the value of text_input_mean something happens, but there is no change either. I tried another way to by following this link, that's why is part of my code you can see:
button.on_click(generate_normal_df)
curdoc().add_root(layout)
which I have later commented. But when I use these two lines of code I get the following error:
Also the line:
button.on_click(button_click_handler)
is causing another error in my IDE. When I use button_click_handler() I get the following error:
File "C:\Users\E17538\anaconda3\lib\site-packages\bokeh\model.py", line 609, in _attach_document raise RuntimeError("Models must be owned by only a single document, %r is already in a doc" % (self)) RuntimeError: Models must be owned by only a single document, WidgetBox(id='1009', ...) is already in a doc
When I use it without (), I get again the same error. I appreciate if you guide me how I can bind the handlers to my widgets. Thank you very much.