Add wx.Timer and wx.CallLater

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@69193 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2011-09-25 04:21:11 +00:00
parent 6fe99f038a
commit 5de01f8ab6
4 changed files with 244 additions and 86 deletions

View File

@@ -82,6 +82,7 @@ INCLUDES = [ 'defs',
'apptrait', 'apptrait',
'app', 'app',
'timer',
'window', 'window',
'validate', 'validate',
'panel', 'panel',

65
etg/timer.py Normal file
View File

@@ -0,0 +1,65 @@
#---------------------------------------------------------------------------
# Name: etg/timer.py
# Author: Robin Dunn
#
# Created: 21-Sept-2011
# Copyright: (c) 2011 by Total Control Software
# License: wxWindows License
#---------------------------------------------------------------------------
import etgtools
import etgtools.tweaker_tools as tools
PACKAGE = "wx"
MODULE = "_core"
NAME = "timer" # Base name of the file to generate to for this script
DOCSTRING = ""
# The classes and/or the basename of the Doxygen XML files to be processed by
# this script.
ITEMS = [ 'wxTimer',
'wxTimerRunner',
'wxTimerEvent',
]
#---------------------------------------------------------------------------
def run():
# Parse the XML file(s) building a collection of Extractor objects
module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING)
etgtools.parseDoxyXML(module, ITEMS)
#-----------------------------------------------------------------
# Tweak the parsed meta objects in the module object as needed for
# customizing the generated code and docstrings.
c = module.find('wxTimer')
assert isinstance(c, etgtools.ClassDef)
c = module.find('wxTimerRunner')
c.addPrivateCopyCtor()
module.addPyCode('EVT_TIMER = wx.PyEventBinder( wxEVT_TIMER )')
module.addPyCode("""\
class PyTimer(Timer):
'''This timer class is passed the callable object to be called when the timer expires.'''
def __init__(self, notify):
Timer.__init__(self)
self.notify = notify
def Notify(self):
if self.notify:
self.notify()
""")
#-----------------------------------------------------------------
tools.doCommonTweaks(module)
tools.addGetterSetterProps(module)
tools.runGenerators(module)
#---------------------------------------------------------------------------
if __name__ == '__main__':
run()

View File

@@ -49,14 +49,13 @@ def deprecated(item, msg=''):
""" """
import warnings import warnings
if isinstance(item, type): if isinstance(item, type):
# It's a class. Make a subclass that raises a warning. # It is a class. Make a subclass that raises a warning.
class DeprecatedClassProxy(item): class DeprecatedClassProxy(item):
def __init__(*args, **kw): def __init__(*args, **kw):
warnings.warn("Using deprecated class. %s" % msg, warnings.warn("Using deprecated class. %s" % msg,
wxPyDeprecationWarning, stacklevel=2) wxPyDeprecationWarning, stacklevel=2)
item.__init__(*args, **kw) item.__init__(*args, **kw)
DeprecatedClassProxy.__name__ = item.__name__ DeprecatedClassProxy.__name__ = item.__name__
DeprecatedClassProxy.__doc__ = item.__doc__
return DeprecatedClassProxy return DeprecatedClassProxy
elif callable(item): elif callable(item):
@@ -191,103 +190,103 @@ def CallAfter(callableObj, *args, **kw):
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
## class CallLater: class CallLater(object):
## """ """
## A convenience class for `wx.Timer`, that calls the given callable A convenience class for `wx.Timer`, that calls the given callable
## object once after the given amount of milliseconds, passing any object once after the given amount of milliseconds, passing any
## positional or keyword args. The return value of the callable is positional or keyword args. The return value of the callable is
## availbale after it has been run with the `GetResult` method. availbale after it has been run with the `GetResult` method.
If you don't need to get the return value or restart the timer
then there is no need to hold a reference to this object. It will
hold a reference to itself while the timer is running (the timer
has a reference to self.Notify) but the cycle will be broken when
the timer completes, automatically cleaning up the wx.CallLater
object.
:see: `wx.CallAfter`
"""
def __init__(self, millis, callableObj, *args, **kwargs):
assert callable(callableObj), "callableObj is not callable"
self.millis = millis
self.callable = callableObj
self.SetArgs(*args, **kwargs)
self.runCount = 0
self.running = False
self.hasRun = False
self.result = None
self.timer = None
self.Start()
## If you don't need to get the return value or restart the timer def __del__(self):
## then there is no need to hold a reference to this object. It will self.Stop()
## hold a reference to itself while the timer is running (the timer
## has a reference to self.Notify) but the cycle will be broken when
## the timer completes, automatically cleaning up the wx.CallLater
## object.
## :see: `wx.CallAfter`
## """
## def __init__(self, millis, callableObj, *args, **kwargs):
## assert callable(callableObj), "callableObj is not callable"
## self.millis = millis
## self.callable = callableObj
## self.SetArgs(*args, **kwargs)
## self.runCount = 0
## self.running = False
## self.hasRun = False
## self.result = None
## self.timer = None
## self.Start()
## def __del__(self):
## self.Stop()
## def Start(self, millis=None, *args, **kwargs): def Start(self, millis=None, *args, **kwargs):
## """ """
## (Re)start the timer (Re)start the timer
## """ """
## self.hasRun = False self.hasRun = False
## if millis is not None: if millis is not None:
## self.millis = millis self.millis = millis
## if args or kwargs: if args or kwargs:
## self.SetArgs(*args, **kwargs) self.SetArgs(*args, **kwargs)
## self.Stop() self.Stop()
## self.timer = wx.PyTimer(self.Notify) self.timer = wx.PyTimer(self.Notify)
## self.timer.Start(self.millis, wx.TIMER_ONE_SHOT) self.timer.Start(self.millis, wx.TIMER_ONE_SHOT)
## self.running = True self.running = True
## Restart = Start Restart = Start
## def Stop(self): def Stop(self):
## """ """
## Stop and destroy the timer. Stop and destroy the timer.
## """ """
## if self.timer is not None: if self.timer is not None:
## self.timer.Stop() self.timer.Stop()
## self.timer = None self.timer = None
## def GetInterval(self): def GetInterval(self):
## if self.timer is not None: if self.timer is not None:
## return self.timer.GetInterval() return self.timer.GetInterval()
## else: else:
## return 0 return 0
## def IsRunning(self): def IsRunning(self):
## return self.timer is not None and self.timer.IsRunning() return self.timer is not None and self.timer.IsRunning()
## def SetArgs(self, *args, **kwargs): def SetArgs(self, *args, **kwargs):
## """ """
## (Re)set the args passed to the callable object. This is (Re)set the args passed to the callable object. This is
## useful in conjunction with Restart if you want to schedule a useful in conjunction with Restart if you want to schedule a
## new call to the same callable object but with different new call to the same callable object but with different
## parameters. parameters.
## """ """
## self.args = args self.args = args
## self.kwargs = kwargs self.kwargs = kwargs
## def HasRun(self): def HasRun(self):
## return self.hasRun return self.hasRun
## def GetResult(self): def GetResult(self):
## return self.result return self.result
## def Notify(self): def Notify(self):
## """ """
## The timer has expired so call the callable. The timer has expired so call the callable.
## """ """
## if self.callable and getattr(self.callable, 'im_self', True): if self.callable and getattr(self.callable, 'im_self', True):
## self.runCount += 1 self.runCount += 1
## self.running = False self.running = False
## self.result = self.callable(*self.args, **self.kwargs) self.result = self.callable(*self.args, **self.kwargs)
## self.hasRun = True self.hasRun = True
## if not self.running: if not self.running:
## # if it wasn't restarted, then cleanup # if it wasn't restarted, then cleanup
## wx.CallAfter(self.Stop) wx.CallAfter(self.Stop)
## Interval = property(GetInterval) Interval = property(GetInterval)
## Result = property(GetResult) Result = property(GetResult)

93
unittests/test_timer.py Normal file
View File

@@ -0,0 +1,93 @@
import imp_unittest, unittest
import wtc
import wx
#---------------------------------------------------------------------------
class timer_Tests(wtc.WidgetTestCase):
def waitFor(self, milliseconds):
intervals = milliseconds/100
while intervals > 0:
wx.MilliSleep(100)
self.myYield()
if hasattr(self, 'flag') and self.flag:
break
intervals -= 1
def onTimerEvt(self, *evt):
self.flag = True
def test_timerOwner1(self):
t = wx.Timer(self.frame)
self.flag = False
self.frame.Bind(wx.EVT_TIMER, self.onTimerEvt, t)
t.Start(250, wx.TIMER_ONE_SHOT)
self.waitFor(500)
self.assertTrue(self.flag)
def test_timerOwner2(self):
t = wx.Timer(self.frame)
self.flag = False
self.frame.Bind(wx.EVT_TIMER, self.onTimerEvt, t)
t.Start(1000, wx.TIMER_ONE_SHOT)
# timer will not have expired yet by this time, so flag shouldn't be set
self.waitFor(500)
self.assertFalse(self.flag)
def test_timerPyTimer(self):
t = wx.PyTimer(self.onTimerEvt)
self.flag = False
t.Start(250, wx.TIMER_ONE_SHOT)
self.waitFor(500)
self.assertTrue(self.flag)
def test_timerDerivedClass(self):
class MyTimer(wx.Timer):
def __init__(self):
wx.Timer.__init__(self)
self.flag = False
def Notify(self):
self.flag = True
t = MyTimer()
t.Start(250, wx.TIMER_ONE_SHOT)
self.waitFor(500)
self.assertTrue(t.flag)
def onCallLater(self):
self.flag = True
return 1234
def test_timerCallLater1(self):
# simple CallLater usage
wx.CallLater(250, self.onCallLater)
self.waitFor(500)
self.assertTrue(self.flag)
def test_timerCallLater2(self):
# test getting the result and restarting the CallLater
cl = wx.CallLater(250, self.onCallLater)
self.assertTrue(cl.IsRunning())
self.waitFor(500)
self.assertTrue(self.flag)
self.assertTrue(cl.GetResult() == 1234)
self.flag = False
cl.Restart()
self.waitFor(500)
self.assertTrue(self.flag)
#---------------------------------------------------------------------------
if __name__ == '__main__':
unittest.main()