tags:

views:

202

answers:

2

In my wxPython app I have an EVT_IDLE handler that calls some function that has to be called once every 150 milliseconds or so. After calling the function, the handler calls:

wx.CallLater(150,self._clear_idle_block_and_do)

That _clear_idle_block_and_do function basically posts another EVT_IDLE event, continuing the cycle.

Now I'm noticing that when other widgets in the GUI are doing hard work, the EVT_IDLE event handler hardly gets called! Sometime it is not called for 4 seconds, which is way too much.

Is this because wx.CallLater is not performing well? Is there anything I could do?

+2  A: 

The wait takes so long, because it waits for idle time. Obviously, if you have "other widgets doing hard work", there won't be idle time soon. If you want a periodic event, use a timer.

MSalters
+1  A: 

Here's a module that creates a timer which does not suffer this problem.

#threadtimer.py

import threading
import time
import wx

wxEVT_THREAD_TIMER = wx.NewEventType()
EVT_THREAD_TIMER = wx.PyEventBinder(wxEVT_THREAD_TIMER, 1)

class ThreadTimer(object):
   def __init__(self, parent):
        self.parent = parent
        self.thread = Thread()
        self.thread.parent = self
        self.alive = False

   def start(self, interval):
       self.interval = interval
       self.alive = True
       self.thread.start()

   def stop(self):
       self.alive = False

class Thread(threading.Thread):
    def run(self):
       while self.parent.alive:
           time.sleep(self.parent.interval / 1000.0)
           event = wx.PyEvent()
           event.SetEventType(wxEVT_THREAD_TIMER)
           wx.PostEvent(self.parent.parent, event)

To use in program:

import threadtimer

timer = threadtimer.ThreadTimer(window)
timer.start(150)
window.Bind(threadtimer.EVT_THREAD_TIMER, function_to_call)
cool-RR