首页 > 解决方案 > 如何使散景 DataTable 响应 DoubleTap

问题描述

我正在尝试添加一个功能来重新计算 diff 列。目前我使用一个按钮来触发回调,但我真的很想通过双击表格中的一行来触发它。
我只能通过使用代码 source.selected.js_on_change('indices', callback) 找到单击实现的解决方案。有谁知道如何让 DataTable 对双击做出反应?

from bokeh.models import ColumnDataSource, TableColumn, DataTable, Div, CustomJS, Button
from bokeh.layouts import column
from bokeh.plotting import show
from bokeh import events

names = ['Alfa', 'Bravo', 'Charlie', 'Delta']
values = [150, 100, 125, 200]
difference = [0, 0, 0, 0]

data = dict(names=names, values=values, diff=difference)
source = ColumnDataSource(data)
columns = [TableColumn(field='names', title='Name', width=200),
           TableColumn(field='values', title='Value (-)', width=200),
           TableColumn(field='diff', title='Difference (%)', width=200)]

# create total table width value
table_width = 0
for col in columns:
    table_width = table_width + col.width
header = Div(text=f'<b>Results<b>', style={'font-size': '150%'})
fig = DataTable(source=source, columns=columns, height=len(values) * 25 + 50, width=table_width, selectable=True)

# callback to change reference for (%) difference calculation
callback = CustomJS(args=dict(source=source), code="""
    var idx = source.selected.indices[0]
    if (typeof idx == "undefined") {
        idx = 0
    }
    var ref_val = source.data['values'][idx]
    console.log(ref_val)
    var d = source.data['diff']
    for (var i = 0; i < d.length; i++) {
        value = source.data['values'][i]
        source.data['diff'][i] = (100*(value/ref_val-1)).toFixed(2)
    }
    source.change.emit()
""")

button = Button()
button.label = 'Click HERE to change reference to selected row for Difference (%) calculation'

# source.selected.js_on_change('indices', callback)
source.selected.js_on_event(events.DoubleTap, callback)
button.js_on_event(events.ButtonClick, callback)

show(column([button, fig]))

标签: pythonbokeh

解决方案


我的技巧是为每行点击设置 2 个活动行。

lst_source_indices_old =[]
source  = ColumnDataSource(df)
    
def callback(attr, old, new):
    global lst_source_indices_old          # declare it is a global variable
    lst = source.selected.indices          # selected row in DataTable
    if(len(lst)==1):
        nrow=lst[0]
        if(lst==lst_source2_indices_old):     
            print("... DataTable : Double-click")
                 
        # Save 
        lst_source2_indices_old  = [nrow] 
        source.selected.indices = [nrow, 9999]     # s.t. every click will be triggered
    
source.selected.on_change('indices', callback)

推荐阅读