Skip to content

Commit 7a7a286

Browse files
committed
-
1 parent 6e3ac5e commit 7a7a286

File tree

4 files changed

+133
-0
lines changed

4 files changed

+133
-0
lines changed

python_toolbox/wx_tools/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@
1919
from . import event_tools
2020
from . import generic_bitmaps
2121
from . import drawing_tools
22+
from . import timing
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from cute_base_timer import CuteBaseTimer
2+
from thread_timer import ThreadTimer
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright 2009-2012 Ram Rachum.
2+
# This program is distributed under the MIT license.
3+
4+
5+
class CuteBaseTimer(object):
6+
'''A base class for timers, allowing easy central stopping.'''
7+
__timers = [] # todo: change to weakref list
8+
9+
def __init__(self, parent):
10+
self.__parent = parent
11+
CuteBaseTimer.__timers.append(self)
12+
13+
14+
@staticmethod # should be classmethod?
15+
def stop_timers_by_frame(frame):
16+
'''Stop all the timers that are associated with the given frame.'''
17+
for timer in CuteBaseTimer.__timers:
18+
ancestor = timer.__parent
19+
while ancestor:
20+
if ancestor == frame:
21+
timer.Stop()
22+
break
23+
ancestor = ancestor.GetParent()
24+
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Copyright 2009-2012 Ram Rachum.
2+
# This program is distributed under the MIT license.
3+
4+
# todo: daemonize?
5+
# todo: kickass idea: make all timers use one thread that will sleep smartly
6+
# to send all events correctly.
7+
8+
import threading
9+
import time
10+
11+
import wx
12+
13+
from python_toolbox.wx_tools.timing import cute_base_timer
14+
15+
16+
wxEVT_THREAD_TIMER = wx.NewEventType()
17+
EVT_THREAD_TIMER = wx.PyEventBinder(wxEVT_THREAD_TIMER, 1)
18+
'''Event saying that a `ThreadTimer` has fired.'''
19+
20+
21+
class ThreadTimer(cute_base_timer.CuteBaseTimer):
22+
'''
23+
A timer for a wxPython app which runs on a different thread.
24+
25+
This solved a problem of wxPython timers being late when the program is
26+
busy.
27+
'''
28+
29+
n = 0
30+
'''The number of created thread timers.'''
31+
32+
33+
_EventHandlerGrokker__event_code = EVT_THREAD_TIMER
34+
35+
36+
def __init__(self, parent):
37+
'''
38+
Construct the ThreadTimer.
39+
40+
`parent` is the parent window.
41+
'''
42+
43+
cute_base_timer.CuteBaseTimer.__init__(self, parent)
44+
45+
self.parent = parent
46+
'''The parent window.'''
47+
48+
ThreadTimer.n += 1
49+
self.wx_id = wx.NewId()
50+
'''The ID of this timer, given by wxPython.'''
51+
52+
self.__init_thread()
53+
self.alive = False
54+
'''Flag saying whether this timer is running.'''
55+
56+
def __init_thread(self):
57+
'''Create the thread.'''
58+
thread_name = ''.join(('Thread used by ThreadTimer no. ', str(self.n)))
59+
self.thread = Thread(self, name=thread_name)
60+
# Overwriting previous thread, so it'll get garbage-collected, hopefully
61+
62+
def start(self, interval):
63+
'''Start the timer.'''
64+
if self.alive:
65+
self.stop()
66+
self.interval = interval
67+
self.alive = True
68+
self.thread.start()
69+
70+
def stop(self):
71+
'''Stop the timer.'''
72+
self.alive = False
73+
self.thread.retired = True
74+
self.__init_thread()
75+
76+
# Crutch for compatibilty with wx.Timer:
77+
Start = start
78+
Stop = stop
79+
80+
def GetId(self):
81+
'''Get the wx ID of this timer.'''
82+
return self.wx_id
83+
84+
85+
class Thread(threading.Thread):
86+
'''Thread used as a timer for wxPython programs.'''
87+
def __init__(self, parent, name):
88+
threading.Thread.__init__(self, name=name)
89+
self.parent = parent
90+
self.retired = False
91+
92+
def run(self):
93+
'''Run the thread. Internal function.'''
94+
interval_in_seconds = self.parent.interval / 1000.0
95+
def sleep():
96+
time.sleep(interval_in_seconds)
97+
98+
sleep()
99+
try:
100+
while self.parent.alive is True and self.retired is False:
101+
event = wx.PyEvent(self.parent.wx_id)
102+
event.SetEventType(wxEVT_THREAD_TIMER)
103+
wx.PostEvent(self.parent.parent, event)
104+
sleep()
105+
except:
106+
return # Just so it wouldn't raise an error when wx is shutting down

0 commit comments

Comments
 (0)