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',
'app',
'timer',
'window',
'validate',
'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
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):
def __init__(*args, **kw):
warnings.warn("Using deprecated class. %s" % msg,
wxPyDeprecationWarning, stacklevel=2)
item.__init__(*args, **kw)
DeprecatedClassProxy.__name__ = item.__name__
DeprecatedClassProxy.__doc__ = item.__doc__
return DeprecatedClassProxy
elif callable(item):
@@ -191,103 +190,103 @@ def CallAfter(callableObj, *args, **kw):
#----------------------------------------------------------------------------
## class CallLater:
## """
## A convenience class for `wx.Timer`, that calls the given callable
## object once after the given amount of milliseconds, passing any
## positional or keyword args. The return value of the callable is
## availbale after it has been run with the `GetResult` method.
class CallLater(object):
"""
A convenience class for `wx.Timer`, that calls the given callable
object once after the given amount of milliseconds, passing any
positional or keyword args. The return value of the callable is
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.
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()
: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 __del__(self):
self.Stop()
## def Start(self, millis=None, *args, **kwargs):
## """
## (Re)start the timer
## """
## self.hasRun = False
## if millis is not None:
## self.millis = millis
## if args or kwargs:
## self.SetArgs(*args, **kwargs)
## self.Stop()
## self.timer = wx.PyTimer(self.Notify)
## self.timer.Start(self.millis, wx.TIMER_ONE_SHOT)
## self.running = True
## Restart = Start
def Start(self, millis=None, *args, **kwargs):
"""
(Re)start the timer
"""
self.hasRun = False
if millis is not None:
self.millis = millis
if args or kwargs:
self.SetArgs(*args, **kwargs)
self.Stop()
self.timer = wx.PyTimer(self.Notify)
self.timer.Start(self.millis, wx.TIMER_ONE_SHOT)
self.running = True
Restart = Start
## def Stop(self):
## """
## Stop and destroy the timer.
## """
## if self.timer is not None:
## self.timer.Stop()
## self.timer = None
def Stop(self):
"""
Stop and destroy the timer.
"""
if self.timer is not None:
self.timer.Stop()
self.timer = None
## def GetInterval(self):
## if self.timer is not None:
## return self.timer.GetInterval()
## else:
## return 0
def GetInterval(self):
if self.timer is not None:
return self.timer.GetInterval()
else:
return 0
## def IsRunning(self):
## return self.timer is not None and self.timer.IsRunning()
def IsRunning(self):
return self.timer is not None and self.timer.IsRunning()
## def SetArgs(self, *args, **kwargs):
## """
## (Re)set the args passed to the callable object. This is
## useful in conjunction with Restart if you want to schedule a
## new call to the same callable object but with different
## parameters.
## """
## self.args = args
## self.kwargs = kwargs
def SetArgs(self, *args, **kwargs):
"""
(Re)set the args passed to the callable object. This is
useful in conjunction with Restart if you want to schedule a
new call to the same callable object but with different
parameters.
"""
self.args = args
self.kwargs = kwargs
## def HasRun(self):
## return self.hasRun
def HasRun(self):
return self.hasRun
## def GetResult(self):
## return self.result
def GetResult(self):
return self.result
## def Notify(self):
## """
## The timer has expired so call the callable.
## """
## if self.callable and getattr(self.callable, 'im_self', True):
## self.runCount += 1
## self.running = False
## self.result = self.callable(*self.args, **self.kwargs)
## self.hasRun = True
## if not self.running:
## # if it wasn't restarted, then cleanup
## wx.CallAfter(self.Stop)
def Notify(self):
"""
The timer has expired so call the callable.
"""
if self.callable and getattr(self.callable, 'im_self', True):
self.runCount += 1
self.running = False
self.result = self.callable(*self.args, **self.kwargs)
self.hasRun = True
if not self.running:
# if it wasn't restarted, then cleanup
wx.CallAfter(self.Stop)
## Interval = property(GetInterval)
## Result = property(GetResult)
Interval = property(GetInterval)
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()