here's a simple example that is not exactly a text-box, but it's a list of lines using the LabelSet() object. The LabelSet() is a way of placing labels at multiple locations within a figure window. It has better support generally including:
- background colors
source= field for ColumnDataSource
- either
data or screen units
If you put the LabelSet locations close enough, with the right sized font it'll look like a text box.
This is an example with a button to update the text with the current date every time it's pressed:
import numpy as np
from datetime import datetime
from bokeh.layouts import layout
from bokeh.io import curdoc
from bokeh.models import ColumnDataSource, Button, LabelSet
from bokeh.plotting import figure
nLines=4 # max number of lines
text_str = ['{0}'.format(line) for line in range(nLines)] # init with empty strings
# create some other data coordinates for a figure
xData=np.arange(-3,+12,0.5)
yData=xData
plot = figure(title="Text placement example, in screen units",
height=300, sizing_mode='scale_width',
x_range=(min(xData), max(xData)), y_range=(min(yData), max(yData)),
x_axis_label="my X-axis", y_axis_label="my Y-axis")
# ------------ text box with a LabelSet() object ----------------
x_scr_lo=20; x_scr_hi=67
label_data = ColumnDataSource(data=dict(
x=[x_scr_lo]*nLines,
y=np.linspace(x_scr_lo,x_scr_hi,nLines),
text=text_str))
plot_label = LabelSet(x='x', y='y', text='text',
text_font_size='11pt',
background_fill_color='lightskyblue',
x_units='screen', y_units='screen',
background_fill_alpha=0.2,
text_color='blue', source=label_data)
plot.add_layout(plot_label)
def bt_add_lines_callback():
new_text=label_data.data['text'] # grab current string list
new_text.pop() # drop the oldest (last)
new_text.insert(0, 'update {0}'.format( datetime.now().strftime('%c') ) )
label_data.data=dict(x=[20]*nLines,
y=np.linspace(x_scr_lo,x_scr_hi,nLines), text=new_text)
bt_add_lines = Button(label="Update next line" ,
button_type="success", width=200)
bt_add_lines.on_click(bt_add_lines_callback)
## arrange all map views in a grid layout then add to the document
layout = layout([
[bt_add_lines],
[plot] ], sizing_mode='stretch_width')
doc = curdoc()
doc.add_root(layout)