]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/Threads.py
2 from wxPython
.wx
import *
6 from whrandom
import random
8 #----------------------------------------------------------------------
10 wxEVT_UPDATE_BARGRAPH
= wxNewEventType()
12 def EVT_UPDATE_BARGRAPH(win
, func
):
13 win
.Connect(-1, -1, wxEVT_UPDATE_BARGRAPH
, func
)
16 class UpdateBarEvent(wxPyEvent
):
17 def __init__(self
, barNum
, value
):
18 wxPyEvent
.__init
__(self
)
19 self
.SetEventType(wxEVT_UPDATE_BARGRAPH
)
24 #----------------------------------------------------------------------
27 def __init__(self
, win
, barNum
, val
):
33 self
.keepGoing
= self
.running
= True
34 thread
.start_new_thread(self
.Run
, ())
37 self
.keepGoing
= False
44 evt
= UpdateBarEvent(self
.barNum
, int(self
.val
))
45 wxPostEvent(self
.win
, evt
)
48 sleeptime
= (random() * 2) + 0.5
49 time
.sleep(sleeptime
/4)
51 sleeptime
= sleeptime
* 5
53 self
.val
= self
.val
+ sleeptime
55 self
.val
= self
.val
- sleeptime
57 if self
.val
< 0: self
.val
= 0
58 if self
.val
> 300: self
.val
= 300
62 #----------------------------------------------------------------------
65 class GraphWindow(wxWindow
):
66 def __init__(self
, parent
, labels
):
67 wxWindow
.__init
__(self
, parent
, -1)
71 self
.values
.append((label
, 0))
73 font
= wxFont(12, wxSWISS
, wxNORMAL
, wxBOLD
)
76 self
.colors
= [ wxRED
, wxGREEN
, wxBLUE
, wxCYAN
,
79 EVT_ERASE_BACKGROUND(self
, self
.OnEraseBackground
)
80 EVT_PAINT(self
, self
.OnPaint
)
83 def SetValue(self
, index
, value
):
84 assert index
< len(self
.values
)
85 cur
= self
.values
[index
]
86 self
.values
[index
:index
+1] = [(cur
[0], value
)]
89 def SetFont(self
, font
):
90 wxWindow
.SetFont(self
, font
)
92 for label
, val
in self
.values
:
93 w
,h
= self
.GetTextExtent(label
)
96 self
.linePos
= wmax
+ 10
100 def GetBestHeight(self
):
101 return 2 * (self
.barHeight
+ 1) * len(self
.values
)
104 def Draw(self
, dc
, size
):
105 dc
.SetFont(self
.GetFont())
106 dc
.SetTextForeground(wxBLUE
)
107 dc
.SetBackground(wxBrush(self
.GetBackgroundColour()))
109 dc
.SetPen(wxPen(wxBLACK
, 3, wxSOLID
))
110 dc
.DrawLine(self
.linePos
, 0, self
.linePos
, size
.height
-10)
112 bh
= ypos
= self
.barHeight
113 for x
in range(len(self
.values
)):
114 label
, val
= self
.values
[x
]
115 dc
.DrawText(label
, 5, ypos
)
118 color
= self
.colors
[ x
% len(self
.colors
) ]
119 dc
.SetPen(wxPen(color
))
120 dc
.SetBrush(wxBrush(color
))
121 dc
.DrawRectangle(self
.linePos
+3, ypos
, val
, bh
)
124 if ypos
> size
.height
-10:
128 def OnPaint(self
, evt
):
129 size
= self
.GetSize()
130 bmp
= wxEmptyBitmap(size
.width
, size
.height
)
135 wdc
= wxPaintDC(self
)
137 wdc
.Blit(0,0, size
.width
, size
.height
, dc
, 0,0)
140 dc
.SelectObject(wxNullBitmap
)
143 def OnEraseBackground(self
, evt
):
149 #----------------------------------------------------------------------
151 class TestFrame(wxFrame
):
152 def __init__(self
, parent
, log
):
153 wxFrame
.__init
__(self
, parent
, -1, "Thread Test", size
=(450,300))
156 #self.CenterOnParent()
158 panel
= wxPanel(self
, -1)
159 panel
.SetFont(wxFont(10, wxSWISS
, wxNORMAL
, wxBOLD
))
160 wxStaticText(panel
, -1,
161 "This demo shows multiple threads interacting with this\n"
162 "window by sending events to it, one thread for each bar.",
166 self
.graph
= GraphWindow(self
, ['Zero', 'One', 'Two', 'Three', 'Four',
167 'Five', 'Six', 'Seven'])
168 self
.graph
.SetSize((450, self
.graph
.GetBestHeight()))
170 sizer
= wxBoxSizer(wxVERTICAL
)
171 sizer
.Add(panel
, 0, wxEXPAND
)
172 sizer
.Add(self
.graph
, 1, wxEXPAND
)
175 self
.SetAutoLayout(True)
178 EVT_UPDATE_BARGRAPH(self
, self
.OnUpdate
)
180 self
.threads
.append(CalcBarThread(self
, 0, 50))
181 self
.threads
.append(CalcBarThread(self
, 1, 75))
182 self
.threads
.append(CalcBarThread(self
, 2, 100))
183 self
.threads
.append(CalcBarThread(self
, 3, 150))
184 self
.threads
.append(CalcBarThread(self
, 4, 225))
185 self
.threads
.append(CalcBarThread(self
, 5, 300))
186 self
.threads
.append(CalcBarThread(self
, 6, 250))
187 self
.threads
.append(CalcBarThread(self
, 7, 175))
189 for t
in self
.threads
:
192 EVT_CLOSE(self
, self
.OnCloseWindow
)
195 def OnUpdate(self
, evt
):
196 self
.graph
.SetValue(evt
.barNum
, evt
.value
)
197 self
.graph
.Refresh(False)
200 def OnCloseWindow(self
, evt
):
201 busy
= wxBusyInfo("One moment please, waiting for threads to die...")
203 for t
in self
.threads
:
208 for t
in self
.threads
:
209 running
= running
+ t
.IsRunning()
215 #----------------------------------------------------------------------
217 def runTest(frame
, nb
, log
):
218 win
= TestFrame(frame
, log
)
223 #----------------------------------------------------------------------
229 The main issue with multi-threaded GUI programming is the thread safty
230 of the GUI itself. On most platforms the GUI is not thread safe and
231 so any cross platform GUI Toolkit and applications written with it
232 need to take that into account.
234 The solution is to only allow interaction with the GUI from a single
235 thread, but this often severly limits what can be done in an
236 application and makes it difficult to use additional threads at all.
238 Since wxPython already makes extensive use of event handlers, it is a
239 logical extension to allow events to be sent to GUI objects from
240 alternate threads. A function called wxPostEvent allows you to do
241 this. It accepts an event and an event handler (window) and instead
242 of sending the event immediately in the current context like
243 ProcessEvent does, it processes it later from the context of the GUI
250 if __name__
== '__main__':
253 run
.main(['', os
.path
.basename(sys
.argv
[0])])