☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

Is there any way to throttle slider control w.r.t arrow keys?

Community Support
Ronald_Truong
Ronald_Truong

For example purposes, I’ll be referring to this sample code, slider.py — Bokeh 2.4.2 Documentation

Is there any way to throttle slider UI input from the user? For example, I want to click on the slider and hold the left or right arrow key to smoothly change the value. For my application, my python callback has some nonzero processing time, so if a user holds the arrow key, the backend is definitely behind. If possible, I’d like the throttle the JS side so this doesn’t happen. Ideas?

⌁   Link to post
Ronald_Truong
Ronald_Truong

Yes I tried the obvious throttling options (value_throttled, callback_throttle) I found on the reference. The current interfaces seemed to only work for mouse actions and / or JS callbacks only.

Some helpful stuff I found below:

⌁   Link to post
Bryan
Bryan

I’m not sure how keyboard events could be throttled with the current implementation. Unlike with the mouse case, there is not any event like “mouse up” that definitively marks the end of user interaction.

Certainly in the immediate term the only suggestion I can suggest is to put the callback on a button next to the slider, which a user could tab to and hit <enter> to click to “activate changes” after they configured the slider (and any other controls)

⌁   Link to post
_jm
_jm

@Ronald_Truong

For what its worth, another option follows using the sliders example cited in your original post. For illustration purposes, I implemented it only on the amplitude slider (amp_slider).

This workaround uses a periodic callback that inspects additional information in the tags attribute and modifies the tags attribute if the slider value has changed. The original amp_slider.js_on_change() is acting on changes to the tags attribute. Because a periodic callback is added to the document, this method requires to run as a bokeh server.

import numpy as np

from bokeh.layouts import column, row
from bokeh.models import CustomJS, Slider
from bokeh.plotting import ColumnDataSource, figure, curdoc

x = np.linspace(0, 10, 500)
y = np.sin(x)

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

plot = figure(y_range=(-10, 10), plot_width=400, plot_height=400)

plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

amp_slider = Slider(start=0.1, end=10, value=1, step=.1, title="Amplitude")
freq_slider = Slider(start=0.1, end=10, value=1, step=.1, title="Frequency")
phase_slider = Slider(start=0, end=6.4, value=0, step=.1, title="Phase")
offset_slider = Slider(start=-5, end=5, value=0, step=.1, title="Offset")


callback = CustomJS(args=dict(source=source, amp=amp_slider, freq=freq_slider, phase=phase_slider, offset=offset_slider),
                    code="""
    const data = source.data;
    const A = amp.value;
    const k = freq.value;
    const phi = phase.value;
    const B = offset.value;
    const x = data['x']
    const y = data['y']
    for (var i = 0; i < x.length; i++) {
        y[i] = B + A*Math.sin(k*x[i]+phi);
    }
    source.change.emit();
""")

amp_slider.js_on_change('tags', callback)
freq_slider.js_on_change('value', callback)
phase_slider.js_on_change('value', callback)
offset_slider.js_on_change('value', callback)

layout = row(
    plot,
    column(amp_slider, freq_slider, phase_slider, offset_slider),
)


amp_slider.tags = [dict(prior_val=amp_slider.value, counter=0)]

def amp_tags_cb():
    if amp_slider.tags[0]['prior_val'] != amp_slider.value:
        amp_slider.tags = [dict(prior_val=amp_slider.value, counter=amp_slider.tags[0]['counter']+1)]

curdoc().add_periodic_callback(amp_tags_cb, period_milliseconds=3000)
curdoc().add_root(layout)
⌁   Link to post

End of archived discussion · Replies are disabled