]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/Threads.py
   9 #---------------------------------------------------------------------- 
  11 # This creates a new Event class and a EVT binder function 
  12 (UpdateBarEvent
, EVT_UPDATE_BARGRAPH
) = wx
.lib
.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             wx
.PostEvent(self
.win
, evt
) 
  38             sleeptime 
= (random
.random() * 2) + 0.5 
  39             time
.sleep(sleeptime
/4) 
  41             sleeptime 
= sleeptime 
* 5 
  42             if int(random
.random() * 2): 
  43                 self
.val 
= self
.val 
+ sleeptime
 
  45                 self
.val 
= self
.val 
- sleeptime
 
  47             if self
.val 
< 0: self
.val 
= 0 
  48             if self
.val 
> 300: self
.val 
= 300 
  52 #---------------------------------------------------------------------- 
  55 class GraphWindow(wx
.Window
): 
  56     def __init__(self
, parent
, labels
): 
  57         wx
.Window
.__init
__(self
, parent
, -1) 
  61             self
.values
.append((label
, 0)) 
  63         font 
= wx
.Font(12, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
) 
  66         self
.colors 
= [ wx
.RED
, wx
.GREEN
, wx
.BLUE
, wx
.CYAN
, 
  69         self
.Bind(wx
.EVT_ERASE_BACKGROUND
, self
.OnEraseBackground
) 
  70         self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
) 
  73     def SetValue(self
, index
, value
): 
  74         assert index 
< len(self
.values
) 
  75         cur 
= self
.values
[index
] 
  76         self
.values
[index
:index
+1] = [(cur
[0], value
)] 
  79     def SetFont(self
, font
): 
  80         wx
.Window
.SetFont(self
, font
) 
  82         for label
, val 
in self
.values
: 
  83             w
,h 
= self
.GetTextExtent(label
) 
  86         self
.linePos 
= wmax 
+ 10 
  90     def GetBestHeight(self
): 
  91         return 2 * (self
.barHeight 
+ 1) * len(self
.values
) 
  94     def Draw(self
, dc
, size
): 
  95         dc
.SetFont(self
.GetFont()) 
  96         dc
.SetTextForeground(wx
.BLUE
) 
  97         dc
.SetBackground(wx
.Brush(self
.GetBackgroundColour())) 
  99         dc
.SetPen(wx
.Pen(wx
.BLACK
, 3, wx
.SOLID
)) 
 100         dc
.DrawLine(self
.linePos
, 0, self
.linePos
, size
.height
-10) 
 102         bh 
= ypos 
= self
.barHeight
 
 103         for x 
in range(len(self
.values
)): 
 104             label
, val 
= self
.values
[x
] 
 105             dc
.DrawText(label
, 5, ypos
) 
 108                 color 
= self
.colors
[ x 
% len(self
.colors
) ] 
 109                 dc
.SetPen(wx
.Pen(color
)) 
 110                 dc
.SetBrush(wx
.Brush(color
)) 
 111                 dc
.DrawRectangle(self
.linePos
+3, ypos
, val
, bh
) 
 114             if ypos 
> size
[1]-10: 
 118     def OnPaint(self
, evt
): 
 119         width
, height 
= size 
=self
.GetSize() 
 120         bmp 
= wx
.EmptyBitmap(width
, height
) 
 128         wdc 
= wx
.PaintDC(self
) 
 130         wdc
.Blit(0,0, size
[0], size
[1], dc
, 0,0) 
 133         dc
.SelectObject(wx
.NullBitmap
) 
 136     def OnEraseBackground(self
, evt
): 
 142 #---------------------------------------------------------------------- 
 144 class TestFrame(wx
.Frame
): 
 145     def __init__(self
, parent
, log
): 
 146         wx
.Frame
.__init
__(self
, parent
, -1, "Thread Test", size
=(450,300)) 
 149         #self.CenterOnParent() 
 151         panel 
= wx
.Panel(self
, -1) 
 152         panel
.SetFont(wx
.Font(10, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
)) 
 153         wx
.StaticText(panel
, -1, 
 154                      "This demo shows multiple threads interacting with this\n" 
 155                      "window by sending events to it, one thread for each bar.", 
 159         self
.graph 
= GraphWindow(self
, ['Zero', 'One', 'Two', 'Three', 'Four', 
 160                                         'Five', 'Six', 'Seven']) 
 161         self
.graph
.SetSize((450, self
.graph
.GetBestHeight())) 
 163         sizer 
= wx
.BoxSizer(wx
.VERTICAL
) 
 164         sizer
.Add(panel
, 0, wx
.EXPAND
) 
 165         sizer
.Add(self
.graph
, 1, wx
.EXPAND
) 
 168         self
.SetAutoLayout(True) 
 171         self
.Bind(EVT_UPDATE_BARGRAPH
, self
.OnUpdate
) 
 174         self
.threads
.append(CalcBarThread(self
, 0, 50)) 
 175         self
.threads
.append(CalcBarThread(self
, 1, 75)) 
 176         self
.threads
.append(CalcBarThread(self
, 2, 100)) 
 177         self
.threads
.append(CalcBarThread(self
, 3, 150)) 
 178         self
.threads
.append(CalcBarThread(self
, 4, 225)) 
 179         self
.threads
.append(CalcBarThread(self
, 5, 300)) 
 180         self
.threads
.append(CalcBarThread(self
, 6, 250)) 
 181         self
.threads
.append(CalcBarThread(self
, 7, 175)) 
 183         for t 
in self
.threads
: 
 186         self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
) 
 189     def OnUpdate(self
, evt
): 
 190         self
.graph
.SetValue(evt
.barNum
, evt
.value
) 
 191         self
.graph
.Refresh(False) 
 194     def OnCloseWindow(self
, evt
): 
 195         busy 
= wx
.BusyInfo("One moment please, waiting for threads to die...") 
 198         for t 
in self
.threads
: 
 206             for t 
in self
.threads
: 
 207                 running 
= running 
+ t
.IsRunning() 
 215 #--------------------------------------------------------------------------- 
 217 class TestPanel(wx
.Panel
): 
 218     def __init__(self
, parent
, log
): 
 220         wx
.Panel
.__init
__(self
, parent
, -1) 
 222         b 
= wx
.Button(self
, -1, "Show Threads sample", (50,50)) 
 223         self
.Bind(wx
.EVT_BUTTON
, self
.OnButton
, b
) 
 226     def OnButton(self
, evt
): 
 227         win 
= TestFrame(self
, self
.log
) 
 231 #--------------------------------------------------------------------------- 
 234 def runTest(frame
, nb
, log
): 
 235     win 
= TestPanel(nb
, log
) 
 238 #---------------------------------------------------------------------- 
 245 The main issue with multi-threaded GUI programming is the thread safty 
 246 of the GUI itself.  On most platforms the GUI is not thread safe and 
 247 so any cross platform GUI Toolkit and applications written with it 
 248 need to take that into account. 
 250 The solution is to only allow interaction with the GUI from a single 
 251 thread, but this often severely limits what can be done in an 
 252 application and makes it difficult to use additional threads at all. 
 254 Since wxPython already makes extensive use of event handlers, it is a 
 255 logical extension to allow events to be sent to GUI objects from 
 256 alternate threads.  A function called wx.PostEvent allows you to do 
 257 this.  It accepts an event and an event handler (window) and instead 
 258 of sending the event immediately in the current context like 
 259 ProcessEvent does, it processes it later from the context of the GUI 
 266 if __name__ 
== '__main__': 
 269     run
.main(['', os
.path
.basename(sys
.argv
[0])] + sys
.argv
[1:])