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