]> git.saurik.com Git - wxWidgets.git/blame - utils/wxPython/demo/Threads.py
it is now possible to add custom buttons into wxHtmlHelpFrame's toolbar
[wxWidgets.git] / utils / wxPython / demo / Threads.py
CommitLineData
e19b7164
RD
1
2from wxPython.wx import *
3
4import thread
5import time
6from whrandom import random
7
8#----------------------------------------------------------------------
9
10wxEVT_UPDATE_BARGRAPH = 25015
11
12def EVT_UPDATE_BARGRAPH(win, func):
13 win.Connect(-1, -1, wxEVT_UPDATE_BARGRAPH, func)
14
15
16class UpdateBarEvent(wxPyEvent):
17 def __init__(self, barNum, value):
18 wxPyEvent.__init__(self)
19 self.SetEventType(wxEVT_UPDATE_BARGRAPH)
20 self.barNum = barNum
21 self.value = value
22
23
24#----------------------------------------------------------------------
25
26class CalcBarThread:
27 def __init__(self, win, barNum, val):
28 self.win = win
29 self.barNum = barNum
30 self.val = val
31
32 def Start(self):
33 self.keepGoing = self.running = true
34 thread.start_new_thread(self.Run, ())
35
36 def Stop(self):
37 self.keepGoing = false
38
39 def IsRunning(self):
40 return self.running
41
42 def Run(self):
43 while self.keepGoing:
44 evt = UpdateBarEvent(self.barNum, int(self.val))
45 wxPostEvent(self.win, evt)
46 del evt
47
48 sleeptime = (random() * 2) + 0.5
49 #print self.barNum, 'sleeping for', sleeptime
50 time.sleep(sleeptime)
51
52 sleeptime = sleeptime * 5
53 if int(random() * 2):
54 self.val = self.val + sleeptime
55 else:
56 self.val = self.val - sleeptime
57
58 if self.val < 0: self.val = 0
59 if self.val > 300: self.val = 300
60
61 self.running = false
62
63#----------------------------------------------------------------------
64
65
66class GraphWindow(wxWindow):
67 def __init__(self, parent, labels):
68 wxWindow.__init__(self, parent, -1)
69
70 self.values = []
71 for label in labels:
72 self.values.append((label, 0))
73
74 self.font = wxFont(12, wxSWISS, wxNORMAL, wxBOLD)
75 self.SetFont(self.font)
76
6230a84f
RD
77 self.colors = [ wxRED, wxGREEN, wxBLUE, wxCYAN,
78 wxNamedColour("Yellow"), wxNamedColor("Navy") ]
e19b7164
RD
79
80
81 def SetValue(self, index, value):
82 assert index < len(self.values)
83 cur = self.values[index]
84 self.values[index:index+1] = [(cur[0], value)]
85
86
87 def SetFont(self, font):
88 wxWindow.SetFont(self, font)
89 wmax = hmax = 0
90 for label, val in self.values:
91 w,h = self.GetTextExtent(label)
92 if w > wmax: wmax = w
93 if h > hmax: hmax = h
94 self.linePos = wmax + 10
95 self.barHeight = hmax
96
97
6230a84f 98 def Draw(self, dc, size):
e19b7164
RD
99 dc.SetFont(self.font)
100 dc.SetTextForeground(wxBLUE)
6230a84f
RD
101 dc.SetBackground(wxBrush(self.GetBackgroundColour()))
102 dc.Clear()
e19b7164
RD
103 dc.SetPen(wxPen(wxBLACK, 3, wxSOLID))
104 dc.DrawLine(self.linePos, 0, self.linePos, size.height-10)
105
106 bh = ypos = self.barHeight
107 for x in range(len(self.values)):
108 label, val = self.values[x]
109 dc.DrawText(label, 5, ypos)
110
111 if val:
112 color = self.colors[ x % len(self.colors) ]
113 dc.SetPen(wxPen(color))
114 dc.SetBrush(wxBrush(color))
115 dc.DrawRectangle(self.linePos+3, ypos, val, bh)
116
117 ypos = ypos + 2*bh
118 if ypos > size.height-10:
119 break
120
6230a84f
RD
121
122 def OnPaint(self, evt):
123 size = self.GetSize()
124 bmp = wxEmptyBitmap(size.width, size.height)
125 dc = wxMemoryDC()
126 dc.SelectObject(bmp)
127 self.Draw(dc, size)
128
129 wdc = wxPaintDC(self)
130 wdc.BeginDrawing()
131 wdc.Blit(0,0, size.width, size.height, dc, 0,0)
132 wdc.EndDrawing()
133
3af4e610
RD
134 dc.SelectObject(wxNullBitmap)
135
6230a84f
RD
136
137 def OnEraseBackground(self, evt):
138 pass
139
140
e19b7164
RD
141
142
143#----------------------------------------------------------------------
144
145class TestFrame(wxFrame):
146 def __init__(self, parent, log):
147 wxFrame.__init__(self, parent, -1, "Thread Test", size=(450,300))
148 self.log = log
149
150 #self.CenterOnParent()
151
152 panel = wxPanel(self, -1)
153 panel.SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD))
154 wxStaticText(panel, -1,
155 "This demo shows multiple threads interacting with this\n"
156 "window by sending events to it.", wxPoint(5,5))
157 panel.Fit()
158
6230a84f
RD
159 self.graph = GraphWindow(self, ['Zero', 'One', 'Two', 'Three', 'Four',
160 'Five', 'Six', 'Seven'])
e19b7164
RD
161
162 sizer = wxBoxSizer(wxVERTICAL)
163 sizer.Add(panel, 0, wxEXPAND)
164 sizer.Add(self.graph, 1, wxEXPAND)
165
166 self.SetSizer(sizer)
167 self.SetAutoLayout(true)
168
169 #self.graph.SetValue(0, 25)
170 #self.graph.SetValue(1, 50)
171 #self.graph.SetValue(2, 75)
172 #self.graph.SetValue(3, 100)
173
174 EVT_UPDATE_BARGRAPH(self, self.OnUpdate)
175 self.threads = []
6230a84f
RD
176 self.threads.append(CalcBarThread(self, 0, 50))
177 self.threads.append(CalcBarThread(self, 1, 75))
178 self.threads.append(CalcBarThread(self, 2, 100))
179 self.threads.append(CalcBarThread(self, 3, 150))
180 self.threads.append(CalcBarThread(self, 4, 225))
181 self.threads.append(CalcBarThread(self, 5, 300))
182 self.threads.append(CalcBarThread(self, 6, 250))
183 self.threads.append(CalcBarThread(self, 7, 175))
e19b7164
RD
184
185 for t in self.threads:
186 t.Start()
187
188
189
190 def OnUpdate(self, evt):
191 self.graph.SetValue(evt.barNum, evt.value)
6230a84f 192 self.graph.Refresh(false)
e19b7164
RD
193
194
195 def OnCloseWindow(self, evt):
196 busy = wxBusyInfo("One moment please, waiting for threads to die...")
197 for t in self.threads:
198 t.Stop()
199 running = 1
200 while running:
201 running = 0
202 for t in self.threads:
203 running = running + t.IsRunning()
204 time.sleep(0.1)
205 self.Destroy()
206
207
208
209#----------------------------------------------------------------------
210
211def runTest(frame, nb, log):
212 win = TestFrame(frame, log)
213 frame.otherWin = win
214 win.Show(true)
215 return None
216
217#----------------------------------------------------------------------
218
219
220
221
222overview = """\
223The main issue with multi-threaded GUI programming is the thread safty
224of the GUI itself. On most platforms the GUI is not thread safe and
225so any cross platform GUI Toolkit and applications written with it
226need to take that into account.
227
228The solution is to only allow interaction with the GUI from a single
229thread, but this often severly limits what can be done in an
230application and makes it difficult to use additional threads at all.
231
232Since wxPython already makes extensive use of event handlers, it is a
233logical extension to allow events to be sent to GUI objects from
234alternate threads. A function called wxPostEvent allows you to do
235this. It accepts an event and an event handler (window) and instead
236of sending the event immediately in the current context like
237ProcessEvent does, it processes it later from the context of the GUI
238thread.
239
240"""