| 1 | import time |
| 2 | import wx |
| 3 | import wx.lib.scrolledpanel as sp |
| 4 | |
| 5 | #---------------------------------------------------------------------- |
| 6 | |
| 7 | |
| 8 | header = """\ |
| 9 | This demo shows the various ways that wx.Timers can be used in your code. Just |
| 10 | select one of the buttons in the left column to start a timer in the indicated way, |
| 11 | and watch the log window below for messages printed when the timer event or callback |
| 12 | happens. Clicking the corresponding button on the right will stop that timer. Since |
| 13 | timers are not owned by any other wx object you should hold on to a reference to the |
| 14 | timer until you are completely finished with it. """ |
| 15 | |
| 16 | doc1 = """\ |
| 17 | Binding an event handler to the wx.EVT_TIMER event is the |
| 18 | prefered way to use the wx.Timer class directly. It makes |
| 19 | handling timer events work just like normal window events. You |
| 20 | just need to specify the window that is to receive the event in |
| 21 | the wx.Timer constructor. If that window needs to be able to |
| 22 | receive events from more than one timer then you can optionally |
| 23 | specify an ID for the timer and the event binding. |
| 24 | """ |
| 25 | |
| 26 | |
| 27 | doc2 = """\ |
| 28 | wx.FutureCall is a convenience class for wx.Timer. You just |
| 29 | specify the timeout in milliseconds and a callable object, along |
| 30 | with any ard or keyword arg you woudl like to be passed to your |
| 31 | callable, and wx.FutureCall takes care of the rest. If you don't |
| 32 | need to get the return value of the callable or to restart the |
| 33 | timer then there is no need to hold a reference to this object. |
| 34 | """ |
| 35 | |
| 36 | |
| 37 | doc3 = """\ |
| 38 | If you derive a class from wx.Timer and give it a Notify method |
| 39 | then it will be called when the timer expires. |
| 40 | """ |
| 41 | |
| 42 | |
| 43 | doc4 = """\ |
| 44 | wx.PyTimer is the old way (a kludge that goes back all the way to |
| 45 | the first version of wxPython) to bind a timer directly to a |
| 46 | callable. You should migrate any code that uses this method to |
| 47 | use EVT_TIMER instead as this may be deprecated in the future. |
| 48 | """ |
| 49 | |
| 50 | |
| 51 | class TestPanel(sp.ScrolledPanel): |
| 52 | def __init__(self, parent, log): |
| 53 | self.log = log |
| 54 | sp.ScrolledPanel.__init__(self, parent, -1) |
| 55 | |
| 56 | outsideSizer = wx.BoxSizer(wx.VERTICAL) |
| 57 | |
| 58 | text = wx.StaticText(self, -1, "wx.Timer", style=wx.ALIGN_CENTRE) |
| 59 | text.SetFont(wx.Font(24, wx.SWISS, wx.NORMAL, wx.BOLD, False)) |
| 60 | text.SetSize(text.GetBestSize()) |
| 61 | text.SetForegroundColour(wx.BLUE) |
| 62 | outsideSizer.Add(text, 0, wx.EXPAND|wx.ALL, 5) |
| 63 | outsideSizer.Add(wx.StaticText(self, -1, header), 0, wx.ALIGN_CENTER|wx.ALL, 5) |
| 64 | outsideSizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND) |
| 65 | outsideSizer.Add((20,20)) |
| 66 | |
| 67 | |
| 68 | t1b1 = wx.Button(self, -1, "EVT_TIMER") |
| 69 | t1b2 = wx.Button(self, -1, "stop timer") |
| 70 | t1st = wx.StaticText(self, -1, doc1) |
| 71 | t1b2.Disable() |
| 72 | self.Bind(wx.EVT_BUTTON, self.OnTest1Start, t1b1) |
| 73 | self.Bind(wx.EVT_BUTTON, self.OnTest1Stop, t1b2) |
| 74 | |
| 75 | # Bind all EVT_TIMER events to self.OnTest1Timer |
| 76 | self.Bind(wx.EVT_TIMER, self.OnTest1Timer) |
| 77 | |
| 78 | |
| 79 | t2b1 = wx.Button(self, -1, "wx.FutureCall") |
| 80 | t2b2 = wx.Button(self, -1, "stop timer") |
| 81 | t2st = wx.StaticText(self, -1, doc2) |
| 82 | t2b2.Disable() |
| 83 | self.Bind(wx.EVT_BUTTON, self.OnTest2Start, t2b1) |
| 84 | self.Bind(wx.EVT_BUTTON, self.OnTest2Stop, t2b2) |
| 85 | |
| 86 | t3b1 = wx.Button(self, -1, "self.Notify") |
| 87 | t3b2 = wx.Button(self, -1, "stop timer") |
| 88 | t3st = wx.StaticText(self, -1, doc3) |
| 89 | t3b2.Disable() |
| 90 | self.Bind(wx.EVT_BUTTON, self.OnTest3Start, t3b1) |
| 91 | self.Bind(wx.EVT_BUTTON, self.OnTest3Stop, t3b2) |
| 92 | |
| 93 | t4b1 = wx.Button(self, -1, "wx.PyTimer") |
| 94 | t4b2 = wx.Button(self, -1, "stop timer") |
| 95 | t4st = wx.StaticText(self, -1, doc4) |
| 96 | t4b2.Disable() |
| 97 | self.Bind(wx.EVT_BUTTON, self.OnTest4Start, t4b1) |
| 98 | self.Bind(wx.EVT_BUTTON, self.OnTest4Stop, t4b2) |
| 99 | |
| 100 | |
| 101 | self.t1b2 = t1b2 |
| 102 | self.t2b2 = t2b2 |
| 103 | self.t3b2 = t3b2 |
| 104 | self.t4b2 = t4b2 |
| 105 | |
| 106 | fgs = wx.FlexGridSizer(cols=3, hgap=10, vgap=10) |
| 107 | fgs.Add(t1b1) |
| 108 | fgs.Add(t1b2) |
| 109 | fgs.Add(t1st) |
| 110 | |
| 111 | fgs.Add(t2b1) |
| 112 | fgs.Add(t2b2) |
| 113 | fgs.Add(t2st) |
| 114 | |
| 115 | fgs.Add(t3b1) |
| 116 | fgs.Add(t3b2) |
| 117 | fgs.Add(t3st) |
| 118 | |
| 119 | fgs.Add(t4b1) |
| 120 | fgs.Add(t4b2) |
| 121 | fgs.Add(t4st) |
| 122 | |
| 123 | outsideSizer.Add(fgs, 0, wx.ALIGN_CENTER|wx.ALL, 10) |
| 124 | self.SetSizer(outsideSizer) |
| 125 | self.SetupScrolling() |
| 126 | |
| 127 | |
| 128 | # Test 1 shows how to use a timer to generate EVT_TIMER |
| 129 | # events, by passing self to the wx.Timer constructor. The |
| 130 | # event is bound above to the OnTest1Timer method. |
| 131 | |
| 132 | def OnTest1Start(self, evt): |
| 133 | self.t1 = wx.Timer(self) |
| 134 | self.t1.Start(1000) |
| 135 | self.log.write("EVT_TIMER timer started\n") |
| 136 | self.t1b2.Enable() |
| 137 | |
| 138 | def OnTest1Stop(self, evt): |
| 139 | self.t1.Stop() |
| 140 | self.log.write("EVT_TIMER timer stoped\n") |
| 141 | del self.t1 |
| 142 | self.t1b2.Disable() |
| 143 | |
| 144 | def OnTest1Timer(self, evt): |
| 145 | self.log.write("got EVT_TIMER event\n") |
| 146 | |
| 147 | |
| 148 | |
| 149 | # Test 2 shows how to use the wx.FutureCall class. |
| 150 | |
| 151 | def OnTest2Start(self, evt): |
| 152 | # Call OnTest2Timer one second in the future, passing some |
| 153 | # optional arbitrary args. There is no need to hold a |
| 154 | # reference to this one, unless we want to manipulate or query |
| 155 | # it later like we do in the two methods below |
| 156 | self.t2 = wx.FutureCall(1000, self.OnTest2Timer, |
| 157 | 'a', 'b', 'c', one=1, two=2) |
| 158 | self.log.write("FutureCall scheduled\n") |
| 159 | self.t2b2.Enable() |
| 160 | |
| 161 | def OnTest2Stop(self, evt): |
| 162 | self.t2.Stop() |
| 163 | self.log.write("FutureCall stopped, last return value was: %s\n" % |
| 164 | repr(self.t2.GetResult())) |
| 165 | del self.t2 |
| 166 | self.t2b2.Disable() |
| 167 | |
| 168 | def OnTest2Timer(self, *args, **kw): |
| 169 | self.log.write("FutureCall called with args=%s, kwargs=%s\n" % (args, kw)) |
| 170 | |
| 171 | # Normally a FutureCall is one-shot, but we can make it |
| 172 | # recurring just by calling Restart. We can even use a |
| 173 | # different timeout or pass differnt args this time. |
| 174 | self.t2.Restart(1500, "restarted") |
| 175 | |
| 176 | # The return value of this function is saved and can be |
| 177 | # retrived later. See OnTest2Stop above. |
| 178 | return "This is my return value" |
| 179 | |
| 180 | |
| 181 | |
| 182 | # Test 3 shows how to use a class derived from wx.Timer. See |
| 183 | # also the NotifyTimer class below. |
| 184 | |
| 185 | def OnTest3Start(self, evt): |
| 186 | self.t3 = NotifyTimer(self.log) |
| 187 | self.t3.Start(1000) |
| 188 | self.log.write("NotifyTimer timer started\n") |
| 189 | self.t3b2.Enable() |
| 190 | |
| 191 | def OnTest3Stop(self, evt): |
| 192 | self.t3.Stop() |
| 193 | self.log.write("NotifyTimer timer stoped\n") |
| 194 | del self.t3 |
| 195 | self.t3b2.Disable() |
| 196 | |
| 197 | |
| 198 | |
| 199 | # Test 4 shows the old way (a kludge that goes back all the |
| 200 | # way to the first version of wxPython) to bind a timer |
| 201 | # directly to a callable. You should migrate any code that |
| 202 | # uses this method to use EVT_TIMER instead as this may be |
| 203 | # deprecated in the future. |
| 204 | def OnTest4Start(self, evt): |
| 205 | self.t4 = wx.PyTimer(self.OnTest4Timer) |
| 206 | self.t4.Start(1000) |
| 207 | self.log.write("wx.PyTimer timer started\n") |
| 208 | self.t4b2.Enable() |
| 209 | |
| 210 | def OnTest4Stop(self, evt): |
| 211 | self.t4.Stop() |
| 212 | self.log.write("wx.PyTimer timer stoped\n") |
| 213 | del self.t4 |
| 214 | self.t4b2.Disable() |
| 215 | |
| 216 | def OnTest4Timer(self): |
| 217 | self.log.write("got wx.PyTimer event\n") |
| 218 | |
| 219 | |
| 220 | |
| 221 | #---------------------------------------------------------------------- |
| 222 | |
| 223 | |
| 224 | # When deriving from wx.Timer you must provide a Notify method |
| 225 | # that will be called when the timer expires. |
| 226 | class NotifyTimer(wx.Timer): |
| 227 | def __init__(self, log): |
| 228 | wx.Timer.__init__(self) |
| 229 | self.log = log |
| 230 | |
| 231 | def Notify(self): |
| 232 | self.log.write("got NotifyTimer event\n") |
| 233 | |
| 234 | |
| 235 | |
| 236 | #---------------------------------------------------------------------- |
| 237 | |
| 238 | def runTest(frame, nb, log): |
| 239 | win = TestPanel(nb, log) |
| 240 | return win |
| 241 | |
| 242 | |
| 243 | #---------------------------------------------------------------------- |
| 244 | |
| 245 | overview = """<html><body> |
| 246 | <h2><center>wx.Timer</center></h2> |
| 247 | |
| 248 | The wx.Timer class allows you to execute code at specified intervals |
| 249 | from within the wxPython event loop. Timers can be one-shot or |
| 250 | repeating. This demo shows the principle method of using a timer |
| 251 | (with events) as well as the convenient wx.FutureCall class. Also |
| 252 | there are two other usage patterns shown here that have been preserved |
| 253 | for backwards compatibility. |
| 254 | |
| 255 | </body></html> |
| 256 | """ |
| 257 | |
| 258 | |
| 259 | |
| 260 | if __name__ == '__main__': |
| 261 | import sys,os |
| 262 | import run |
| 263 | run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:]) |
| 264 | |
| 265 | |
| 266 | |
| 267 | |