Update the GUI using thread-safe methods. In wxPython, there are 3:
- wx.CallAfter
- wx.CallLater
- wx.PostEvent
You should also take a look the wxPython wiki for information on wxPython and threading:
I also wrote a tutorial on the topic:
UPDATE: Here is a simple example that creates 40 threads and "processes" 40 made up files. It updates the display when each thread is done. However, I do not see the issue you speak of.
import random
import time
import wx
from threading import Thread
from wx.lib.pubsub import Publisher
########################################################################
class TestThread(Thread):
"""Test Worker Thread Class."""
#----------------------------------------------------------------------
def __init__(self, fname, sleepAmt):
"""Init Worker Thread Class."""
Thread.__init__(self)
self.fname = fname
self.sleepAmt = sleepAmt
self.start() # start the thread
#----------------------------------------------------------------------
def run(self):
"""Run Worker Thread."""
# This is the code executing in the new thread.
time.sleep(self.sleepAmt)
msg = "%s finished in %s seconds!" % (self.fname, self.sleepAmt)
wx.CallAfter(Publisher().sendMessage, "update", msg)
########################################################################
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial")
panel = wx.Panel(self, wx.ID_ANY)
self.updateText = wx.TextCtrl(panel, style=wx.TE_MULTILINE)
self.btn = btn = wx.Button(panel, label="Start Thread")
btn.Bind(wx.EVT_BUTTON, self.onButton)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.updateText, 1, wx.ALL|wx.EXPAND, 5)
sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
panel.SetSizer(sizer)
# create a pubsub receiver
Publisher().subscribe(self.updateDisplay, "update")
#----------------------------------------------------------------------
def onButton(self, event):
"""
Runs the thread
"""
for i in range(40):
fname = "test%s.txt" % i
secs = random.choice(range(3, 15))
TestThread(fname, secs)
#----------------------------------------------------------------------
def updateDisplay(self, msg):
"""
Receives data from thread and updates the display
"""
data = msg.data + "\n"
self.updateText.WriteText(data)
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyForm().Show()
app.MainLoop()
I am running on Windows 7 using Python 2.6 with wxPython 2.8.12.1