I have a wx.Slider
widget that is bound to an event handler. As a user moves the slider, some process will run. However, because the process can take up to 3 seconds to run, I don't want the event to fire continuously as the user moves the slider. Instead, I want the event to fire only if the user stops moving the slider for some amount of time (say, 2 seconds). I tried using time.time()
with a while
-loop (see code below), but it didn't work because the event would still fire repeatedly -- it's just that the firing got delayed. Any idea/pointer/suggestion would be greatly appreciated.
import wx
import time
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
pnl = wx.Panel(self)
sld = wx.Slider(pnl, value=200, minValue=150, maxValue=500, pos=(20, 20),
size=(250, -1), style=wx.SL_HORIZONTAL)
self.counter = 0
sld.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
self.txt = wx.StaticText(pnl, label='200', pos=(20, 90))
self.SetSize((290, 200))
self.SetTitle('wx.Slider')
self.Centre()
self.Show(True)
def OnSliderScroll(self, e):
now = time.time()
future = now + 2
while time.time() < future:
pass
#substitute for the actual process.
self.counter += 1
print self.counter
def main():
ex = wx.App()
Example(None)
ex.MainLoop()
if __name__ == '__main__':
main()
Delaying with time.sleep
will block your GUI. Use wx.CallLater
instead, which in the sample below will trigger the delayed event until it has been restarted again.
def InitUi(self):
# ...
# Add a delay timer, set it up and stop it
self.delay_slider_evt = wx.CallLater(2000, self.delayed_event)
self.delay_slider_evt.Stop()
def OnSliderScroll(self, e):
# if delay timer does not run, start it, either restart it
if not self.delay_slider_evt.IsRunning():
self.delay_slider_evt.Start(2000)
else:
self.delay_slider_evt.Restart(2000)
def delayed_event(self):
#substitute for the actual delayed process.
self.counter += 1
print self.counter