Bokeh 简明教程
Bokeh - Adding Widgets
bokeh.models.widgets 模块包含与 HTML 表单元素相似的 GUI 对象的定义,例如按钮、滑块、复选框、单选按钮等。这些控件为绘制图形提供交互式界面。可以通过根据相应事件执行自定义 JavaScript 函数来调用处理,如修改绘制图形数据、更改绘制图形参数等。
The bokeh.models.widgets module contains definitions of GUI objects similar to HTML form elements, such as button, slider, checkbox, radio button, etc. These controls provide interactive interface to a plot. Invoking processing such as modifying plot data, changing plot parameters, etc., can be performed by custom JavaScript functions executed on corresponding events.
Bokeh 允许使用两种方法定义回调功能 −
Bokeh allows call back functionality to be defined with two methods −
-
Use the CustomJS callback so that the interactivity will work in standalone HTML documents.
-
Use Bokeh server and set up event handlers.
在本节中,我们将了解如何添加 Bokeh 控件并分配 JavaScript 回调。
In this section, we shall see how to add Bokeh widgets and assign JavaScript callbacks.
Button
此控件是一个可点击按钮,通常用于调用用户定义的回叫处理程序。构造函数采用以下参数 −
This widget is a clickable button generally used to invoke a user defined call back handler. The constructor takes following parameters −
Button(label, icon, callback)
标签参数是用作按钮标题的字符串,callback 是在单击时要调用的自定义 JavaScript 函数。
The label parameter is a string used as button’s caption and callback is the custom JavaScript function to be called when clicked.
在以下示例中,图和按钮控件显示在 Column 布局中。该图本身在 x 和 y 数据系列之间呈现一条线形符号。
In the following example, a plot and Button widget are displayed in Column layout. The plot itself renders a line glyph between x and y data series.
已使用 CutomJS() function 定义了一个名为“callback”的自定义 JavaScript 函数。它以变量 cb_obj 的形式接收对触发回调的对象(在本例中为按钮)的引用。
A custom JavaScript function named ‘callback’ has been defined using CutomJS() function. It receives reference to the object that triggered callback (in this case the button) in the form variable cb_obj.
此函数更改源 ColumnDataSource 数据,并最终在此源数据中发出此更新。
This function alters the source ColumnDataSource data and finally emits this update in source data.
from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import Figure, output_file, show
from bokeh.models.widgets import Button
x = [x*0.05 for x in range(0, 200)]
y = x
source = ColumnDataSource(data=dict(x=x, y=y))
plot = Figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
callback = CustomJS(args=dict(source=source), code="""
var data = source.data;
x = data['x']
y = data['y']
for (i = 0; i < x.length; i++) {
y[i] = Math.pow(x[i], 4)
}
source.change.emit();
""")
btn = Button(label="click here", callback=callback, name="1")
layout = column(btn , plot)
show(layout)
Slider
借助滑块控件,可以在分配给它的 start 和 end 属性之间选择一个数字。
With the help of a slider control it is possible to select a number between start and end properties assigned to it.
Slider(start, end, step, value)
在以下示例中,我们在滑块的 on_change 事件上注册了一个回调函数。滑块的瞬时数值以 cb_obj.value 的形式提供给处理程序,该值用于修改 ColumnDatasource 数据。随着您滑动位置,该图例会不断更新。
In the following example, we register a callback function on slider’s on_change event. Slider’s instantaneous numeric value is available to the handler in the form of cb_obj.value which is used to modify the ColumnDatasource data. The plot figure continuously updates as you slide the position.
from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import Figure, output_file, show
from bokeh.models.widgets import Slider
x = [x*0.05 for x in range(0, 200)]
y = x
source = ColumnDataSource(data=dict(x=x, y=y))
plot = Figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
handler = CustomJS(args=dict(source=source), code="""
var data = source.data;
var f = cb_obj.value
var x = data['x']
var y = data['y']
for (var i = 0; i < x.length; i++) {
y[i] = Math.pow(x[i], f)
}
source.change.emit();
""")
slider = Slider(start=0.0, end=5, value=1, step=.25, title="Slider Value")
slider.js_on_change('value', handler)
layout = column(slider, plot)
show(layout)
RadioGroup
此控件呈现一组互斥切换按钮,在标题的左侧显示圆形按钮。
This widget presents a collection of mutually exclusive toggle buttons showing circular buttons to the left of caption.
RadioGroup(labels, active)
其中,标签是标题列表,active 是所选选项的索引。
Where, labels is a list of captions and active is the index of selected option.
Select
此控件是一个简单的字符串项下拉列表,可以从中选择一个。所选字符串显示在顶部窗口中,它是值参数。
This widget is a simple dropdown list of string items, one of which can be selected. Selected string appears at the top window and it is the value parameter.
Select(options, value)
下拉列表中的字符串元素列表以 options 列表对象的形式给出。
The list of string elements in the dropdown is given in the form of options list object.
以下是单选按钮和选择控件的组合示例,两个控件都提供了 x 和 y 数据系列之间的三种不同关系。 RadioGroup 和 Select widgets 通过 on_change() 方法向相应的处理程序注册。
Following is a combined example of radio button and select widgets, both providing three different relationships between x and y data series. The RadioGroup and Select widgets are registered with respective handlers through on_change() method.
from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import Figure, output_file, show
from bokeh.models.widgets import RadioGroup, Select
x = [x*0.05 for x in range(0, 200)]
y = x
source = ColumnDataSource(data=dict(x=x, y=y))
plot = Figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
radiohandler = CustomJS(args=dict(source=source), code="""
var data = source.data;
console.log('Tap event occurred at x-position: ' + cb_obj.active);
//plot.title.text=cb_obj.value;
x = data['x']
y = data['y']
if (cb_obj.active==0){
for (i = 0; i < x.length; i++) {
y[i] = x[i];
}
}
if (cb_obj.active==1){
for (i = 0; i < x.length; i++) {
y[i] = Math.pow(x[i], 2)
}
}
if (cb_obj.active==2){
for (i = 0; i < x.length; i++) {
y[i] = Math.pow(x[i], 4)
}
}
source.change.emit();
""")
selecthandler = CustomJS(args=dict(source=source), code="""
var data = source.data;
console.log('Tap event occurred at x-position: ' + cb_obj.value);
//plot.title.text=cb_obj.value;
x = data['x']
y = data['y']
if (cb_obj.value=="line"){
for (i = 0; i < x.length; i++) {
y[i] = x[i];
}
}
if (cb_obj.value=="SquareCurve"){
for (i = 0; i < x.length; i++) {
y[i] = Math.pow(x[i], 2)
}
}
if (cb_obj.value=="CubeCurve"){
for (i = 0; i < x.length; i++) {
y[i] = Math.pow(x[i], 4)
}
}
source.change.emit();
""")
radio = RadioGroup(
labels=["line", "SqureCurve", "CubeCurve"], active=0)
radio.js_on_change('active', radiohandler)
select = Select(title="Select:", value='line', options=["line", "SquareCurve", "CubeCurve"])
select.js_on_change('value', selecthandler)
layout = column(radio, select, plot)
show(layout)
Tab widget
就像在浏览器中一样,每个选项卡都可以显示不同的网页,Tab 控件是 Bokeh 模块,它为每个数字提供不同的视图。在以下示例中,在两个不同的选项卡中渲染了正弦曲线和余弦曲线的两个图例 −
Just as in a browser, each tab can show different web page, the Tab widget is Bokeh model providing different view to each figure. In the following example, two plot figures of sine and cosine curves are rendered in two different tabs −
from bokeh.plotting import figure, output_file, show
from bokeh.models import Panel, Tabs
import numpy as np
import math
x=np.arange(0, math.pi*2, 0.05)
fig1=figure(plot_width=300, plot_height=300)
fig1.line(x, np.sin(x),line_width=2, line_color='navy')
tab1 = Panel(child=fig1, title="sine")
fig2=figure(plot_width=300, plot_height=300)
fig2.line(x,np.cos(x), line_width=2, line_color='orange')
tab2 = Panel(child=fig2, title="cos")
tabs = Tabs(tabs=[ tab1, tab2 ])
show(tabs)