]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/Threads.py
b1dce085a67c2af993fff54a91ec293fde83f4c6
2 from wxPython
.wx
import *
6 from whrandom
import random
8 #----------------------------------------------------------------------
10 wxEVT_UPDATE_BARGRAPH
= 25015
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 #print self.barNum, 'sleeping for', sleeptime
52 sleeptime
= sleeptime
* 5
54 self
.val
= self
.val
+ sleeptime
56 self
.val
= self
.val
- sleeptime
58 if self
.val
< 0: self
.val
= 0
59 if self
.val
> 300: self
.val
= 300
63 #----------------------------------------------------------------------
66 class GraphWindow(wxWindow
):
67 def __init__(self
, parent
, labels
):
68 wxWindow
.__init
__(self
, parent
, -1)
72 self
.values
.append((label
, 0))
74 font
= wxFont(12, wxSWISS
, wxNORMAL
, wxBOLD
)
77 self
.colors
= [ wxRED
, wxGREEN
, wxBLUE
, wxCYAN
,
80 EVT_ERASE_BACKGROUND(self
, self
.OnEraseBackground
)
81 EVT_PAINT(self
, self
.OnPaint
)
84 def SetValue(self
, index
, value
):
85 assert index
< len(self
.values
)
86 cur
= self
.values
[index
]
87 self
.values
[index
:index
+1] = [(cur
[0], value
)]
90 def SetFont(self
, font
):
91 wxWindow
.SetFont(self
, font
)
93 for label
, val
in self
.values
:
94 w
,h
= self
.GetTextExtent(label
)
97 self
.linePos
= wmax
+ 10
101 def GetBestHeight(self
):
102 return 2 * (self
.barHeight
+ 1) * len(self
.values
)
105 def Draw(self
, dc
, size
):
106 dc
.SetFont(self
.GetFont())
107 dc
.SetTextForeground(wxBLUE
)
108 dc
.SetBackground(wxBrush(self
.GetBackgroundColour()))
110 dc
.SetPen(wxPen(wxBLACK
, 3, wxSOLID
))
111 dc
.DrawLine(self
.linePos
, 0, self
.linePos
, size
.height
-10)
113 bh
= ypos
= self
.barHeight
114 for x
in range(len(self
.values
)):
115 label
, val
= self
.values
[x
]
116 dc
.DrawText(label
, 5, ypos
)
119 color
= self
.colors
[ x
% len(self
.colors
) ]
120 dc
.SetPen(wxPen(color
))
121 dc
.SetBrush(wxBrush(color
))
122 dc
.DrawRectangle(self
.linePos
+3, ypos
, val
, bh
)
125 if ypos
> size
.height
-10:
129 def OnPaint(self
, evt
):
130 size
= self
.GetSize()
131 bmp
= wxEmptyBitmap(size
.width
, size
.height
)
136 wdc
= wxPaintDC(self
)
138 wdc
.Blit(0,0, size
.width
, size
.height
, dc
, 0,0)
141 dc
.SelectObject(wxNullBitmap
)
144 def OnEraseBackground(self
, evt
):
150 #----------------------------------------------------------------------
152 class TestFrame(wxFrame
):
153 def __init__(self
, parent
, log
):
154 wxFrame
.__init
__(self
, parent
, -1, "Thread Test", size
=(450,300))
157 #self.CenterOnParent()
159 panel
= wxPanel(self
, -1)
160 panel
.SetFont(wxFont(10, wxSWISS
, wxNORMAL
, wxBOLD
))
161 wxStaticText(panel
, -1,
162 "This demo shows multiple threads interacting with this\n"
163 "window by sending events to it.", wxPoint(5,5))
166 self
.graph
= GraphWindow(self
, ['Zero', 'One', 'Two', 'Three', 'Four',
167 'Five', 'Six', 'Seven'])
168 self
.graph
.SetSize((-1, 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 #self.graph.SetValue(0, 25)
179 #self.graph.SetValue(1, 50)
180 #self.graph.SetValue(2, 75)
181 #self.graph.SetValue(3, 100)
183 EVT_UPDATE_BARGRAPH(self
, self
.OnUpdate
)
185 self
.threads
.append(CalcBarThread(self
, 0, 50))
186 self
.threads
.append(CalcBarThread(self
, 1, 75))
187 self
.threads
.append(CalcBarThread(self
, 2, 100))
188 self
.threads
.append(CalcBarThread(self
, 3, 150))
189 self
.threads
.append(CalcBarThread(self
, 4, 225))
190 self
.threads
.append(CalcBarThread(self
, 5, 300))
191 self
.threads
.append(CalcBarThread(self
, 6, 250))
192 self
.threads
.append(CalcBarThread(self
, 7, 175))
194 for t
in self
.threads
:
197 EVT_CLOSE(self
, self
.OnCloseWindow
)
200 def OnUpdate(self
, evt
):
201 self
.graph
.SetValue(evt
.barNum
, evt
.value
)
202 self
.graph
.Refresh(false
)
205 def OnCloseWindow(self
, evt
):
206 busy
= wxBusyInfo("One moment please, waiting for threads to die...")
207 for t
in self
.threads
:
212 for t
in self
.threads
:
213 running
= running
+ t
.IsRunning()
219 #----------------------------------------------------------------------
221 def runTest(frame
, nb
, log
):
222 win
= TestFrame(frame
, log
)
227 #----------------------------------------------------------------------
233 The main issue with multi-threaded GUI programming is the thread safty
234 of the GUI itself. On most platforms the GUI is not thread safe and
235 so any cross platform GUI Toolkit and applications written with it
236 need to take that into account.
238 The solution is to only allow interaction with the GUI from a single
239 thread, but this often severly limits what can be done in an
240 application and makes it difficult to use additional threads at all.
242 Since wxPython already makes extensive use of event handlers, it is a
243 logical extension to allow events to be sent to GUI objects from
244 alternate threads. A function called wxPostEvent allows you to do
245 this. It accepts an event and an event handler (window) and instead
246 of sending the event immediately in the current context like
247 ProcessEvent does, it processes it later from the context of the GUI