]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/Threads.py
2 from wxPython
.wx
import *
3 from wxPython
.lib
import newevent
7 from whrandom
import random
9 #----------------------------------------------------------------------
11 # This creates a new Event class and a EVT binder function
12 UpdateBarEvent
, EVT_UPDATE_BARGRAPH
= newevent
.NewEvent()
15 #----------------------------------------------------------------------
18 def __init__(self
, win
, barNum
, val
):
24 self
.keepGoing
= self
.running
= True
25 thread
.start_new_thread(self
.Run
, ())
28 self
.keepGoing
= False
35 evt
= UpdateBarEvent(barNum
= self
.barNum
, value
= int(self
.val
))
36 wxPostEvent(self
.win
, evt
)
39 sleeptime
= (random() * 2) + 0.5
40 time
.sleep(sleeptime
/4)
42 sleeptime
= sleeptime
* 5
44 self
.val
= self
.val
+ sleeptime
46 self
.val
= self
.val
- sleeptime
48 if self
.val
< 0: self
.val
= 0
49 if self
.val
> 300: self
.val
= 300
53 #----------------------------------------------------------------------
56 class GraphWindow(wxWindow
):
57 def __init__(self
, parent
, labels
):
58 wxWindow
.__init
__(self
, parent
, -1)
62 self
.values
.append((label
, 0))
64 font
= wxFont(12, wxSWISS
, wxNORMAL
, wxBOLD
)
67 self
.colors
= [ wxRED
, wxGREEN
, wxBLUE
, wxCYAN
,
70 EVT_ERASE_BACKGROUND(self
, self
.OnEraseBackground
)
71 EVT_PAINT(self
, self
.OnPaint
)
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
)]
80 def SetFont(self
, font
):
81 wxWindow
.SetFont(self
, font
)
83 for label
, val
in self
.values
:
84 w
,h
= self
.GetTextExtent(label
)
87 self
.linePos
= wmax
+ 10
91 def GetBestHeight(self
):
92 return 2 * (self
.barHeight
+ 1) * len(self
.values
)
95 def Draw(self
, dc
, size
):
96 dc
.SetFont(self
.GetFont())
97 dc
.SetTextForeground(wxBLUE
)
98 dc
.SetBackground(wxBrush(self
.GetBackgroundColour()))
100 dc
.SetPen(wxPen(wxBLACK
, 3, wxSOLID
))
101 dc
.DrawLine((self
.linePos
, 0), (self
.linePos
, size
.height
-10))
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
))
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
))
115 if ypos
> size
.height
-10:
119 def OnPaint(self
, evt
):
120 size
= self
.GetSize()
121 bmp
= wxEmptyBitmap(size
.width
, size
.height
)
126 wdc
= wxPaintDC(self
)
128 wdc
.Blit((0,0), size
, dc
, (0,0))
131 dc
.SelectObject(wxNullBitmap
)
134 def OnEraseBackground(self
, evt
):
140 #----------------------------------------------------------------------
142 class TestFrame(wxFrame
):
143 def __init__(self
, parent
, log
):
144 wxFrame
.__init
__(self
, parent
, -1, "Thread Test", size
=(450,300))
147 #self.CenterOnParent()
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"
153 "window by sending events to it, one thread for each bar.",
157 self
.graph
= GraphWindow(self
, ['Zero', 'One', 'Two', 'Three', 'Four',
158 'Five', 'Six', 'Seven'])
159 self
.graph
.SetSize((450, self
.graph
.GetBestHeight()))
161 sizer
= wxBoxSizer(wxVERTICAL
)
162 sizer
.Add(panel
, 0, wxEXPAND
)
163 sizer
.Add(self
.graph
, 1, wxEXPAND
)
166 self
.SetAutoLayout(True)
169 EVT_UPDATE_BARGRAPH(self
, self
.OnUpdate
)
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))
180 for t
in self
.threads
:
183 EVT_CLOSE(self
, self
.OnCloseWindow
)
186 def OnUpdate(self
, evt
):
187 self
.graph
.SetValue(evt
.barNum
, evt
.value
)
188 self
.graph
.Refresh(False)
191 def OnCloseWindow(self
, evt
):
192 busy
= wxBusyInfo("One moment please, waiting for threads to die...")
194 for t
in self
.threads
:
199 for t
in self
.threads
:
200 running
= running
+ t
.IsRunning()
206 #----------------------------------------------------------------------
208 def runTest(frame
, nb
, log
):
209 win
= TestFrame(frame
, log
)
214 #----------------------------------------------------------------------
220 The main issue with multi-threaded GUI programming is the thread safty
221 of the GUI itself. On most platforms the GUI is not thread safe and
222 so any cross platform GUI Toolkit and applications written with it
223 need to take that into account.
225 The solution is to only allow interaction with the GUI from a single
226 thread, but this often severely limits what can be done in an
227 application and makes it difficult to use additional threads at all.
229 Since wxPython already makes extensive use of event handlers, it is a
230 logical extension to allow events to be sent to GUI objects from
231 alternate threads. A function called wxPostEvent allows you to do
232 this. It accepts an event and an event handler (window) and instead
233 of sending the event immediately in the current context like
234 ProcessEvent does, it processes it later from the context of the GUI
241 if __name__
== '__main__':
244 run
.main(['', os
.path
.basename(sys
.argv
[0])])