首页 > 解决方案 > 通过再次单击按钮来反转 Bokeh 按钮操作

问题描述

我有一个仪表板的愿景,您可以在其中单击几个按钮之一来执行附加操作,并通过再次单击该按钮来撤消操作。实际上撤消是错误的词,因为我不希望第二次单击将其恢复到原始状态,因为这可能会干扰另一个按钮的结果,但我希望第二次单击以取出它放入的内容。作为一个示例我有以下问题,其中按下标记为 的按钮Apple,为每个数据点添加一个值3.0,这会更新圆形字形图。我的问题是,“有没有一种方法可以设置代码,再次按下按钮将减去一个值3.0?”

from bokeh.models import ColumnDataSource, CustomJS, Button
from bokeh.plotting import Figure, output_file, show
from bokeh.layouts import column

output_file("js_on_change.html")

x = [1.2, 2.4, 0.8, 5.6, 12.1, 8.8]
y = [3.4, 1.1, 4.2, 6.6, 1.8, 12.1]
z = ['Apple', 'Apple', 'Orange', 'Orange', 'Orange', 'Orange']

data = dict(x=x, y=y, z=z)
source = ColumnDataSource(data)

plot = Figure(plot_width=400, plot_height=400)
plot.circle('x', 'y', source=source, size=8, line_alpha=0.6)

callback1 = CustomJS(args=dict(source=source), code="""
    var data = source.data;
    var f = 3.0
    var x = data['x']
    var y = data['y']
    for (var i = 0; i < x.length; i++) {
        y[i] = y[i] + f
    }
    source.change.emit();
""")

button = Button(label="Apple", button_type="success")
button.js_on_click(callback1)

layout = column(button, plot)

show(layout)

标签: pythonpython-3.xbokeh

解决方案


一种可能的解决方案是向您的自定义 JavaScript 添加第二个 CDS 以计算点击次数。

CustomJS(args=dict(source=source, counter=counter), code="...")

在您的 JavaScript 中,您必须添加几行。如果点击次数是偶数,则添加f,否则将其减去。

var count = counter.data;
var c = count['counter']
if (c[0]%2==1) f = -1*f;
c[0]++
counter.change.emit();

创建的图形将像这样工作:

切换

完整代码

from bokeh.models import ColumnDataSource, CustomJS, Button, Range1d
from bokeh.plotting import Figure, output_notebook, show
from bokeh.layouts import column
output_notebook()

x = [1]
y = [3]
z = ['Apple']

data = dict(x=x, y=y, z=z)
source = ColumnDataSource(data)

counter = [0]
counter = dict(counter=counter)
counter = ColumnDataSource(counter)

plot = Figure(plot_width=400, plot_height=400)
plot.circle('x', 'y', source=source, size=8, line_alpha=0.6)
plot.y_range = Range1d(0,7)

callback1 = CustomJS(args=dict(source=source, counter=counter), code="""
    var f = 3.0
    
    var count = counter.data;
    var c = count['counter']
    if (c[0]%2==1) f = -1*f;
    c[0]++
    counter.change.emit();
    
    var data = source.data;
    var x = data['x']
    var y = data['y']
    for (var i = 0; i < x.length; i++) {
        y[i] = y[i] + f
    }
    source.change.emit();
""")

button = Button(label="Apple", button_type="success")
button.js_on_click(callback1)

layout = column(button, plot)

show(layout)

推荐阅读