Hi,
I need to start a wx.App in a separate thread which seems to work.
However, running the attached example, I get the following traceback
after having created and run the wx.App in its own thread:
Traceback (most recent call last):
File "wxthread.py", line 42, in OnUpdate
self.timer.Start(3000, wx.TIMER_ONE_SHOT)
File "c:\pythonxy\python\lib\site-packages\wx-2.8-msw-unicode\wx
\_misc.py", line 1298, in Start
return _misc_.Timer_Start(*args, **kwargs)
wx._core.PyAssertionError: C++ assertion "wxThread::IsMain()" failed
at ..\..\src\common\timercmn.cpp(66) in wxTimerBase::Start(): timer
can only be started from the main thread
end thread
Any ideas what is happening?
Thanks in advance, Christian
import wx
import wx.lib.newevent
from threading import Thread
import time
(NextEvent, EVT_NEXT) = wx.lib.newevent.NewEvent()
class Listener(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
app = wx.PySimpleApp(0)
self.f = wx.Frame(None)
p = wx.Panel(self.f)
lab = wx.StaticText(p, -1, 'tag report')
self.txt = wx.TextCtrl(p, -1, '', size=(500,150),
style=wx.TE_MULTILINE|wx.TE_READONLY)
box = wx.BoxSizer(wx.VERTICAL)
hbox = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(lab, 1, wx.TOP|wx.BOTTOM|wx.EXPAND, 10)
box.Add(hbox, 0, wx.EXPAND|wx.ALL, 2)
box.Add(self.txt, 1, wx.ALL|wx.EXPAND, 2)
p.SetSizer(box)
p.Fit()
self.f.Fit()
self.f.Show()
self.f.Bind(wx.EVT_CLOSE, self.OnClose)
self.f.Bind(EVT_NEXT, self.OnUpdate)
self.f.Bind(wx.EVT_TIMER, self.OnClose)
app.MainLoop()
print 'end thread'
def OnUpdate(self, evt):
msg = evt.msg
if msg.find('done.') == 0:
self.timer = wx.Timer(self.f)
self.timer.Start(3000, wx.TIMER_ONE_SHOT)
self.txt.SetValue(self.txt.GetValue()+msg)
self.txt.SetInsertionPointEnd()
def OnClose(self, evt):
self.timer.Stop()
del self.timer
self.f.Bind(EVT_NEXT, None)
self.f.Bind(wx.EVT_TIMER, None)
self.f.Bind(wx.EVT_CLOSE, None)
self.f.Destroy()
class Progress:
def __init__(self):
self.t = Listener()
self.t.start()
def next(self, msg='piep\n'):
if self.alive and hasattr(self.t, 'f'):
if msg[-1] != '\n':
msg += '\n'
evt = NextEvent(msg=msg)
wx.PostEvent(self.t.f, evt)
def isalive(self):
return self.t.isAlive()
alive = property(isalive)
def end(self):
del self.t
if __name__ == '__main__':
for l in range(2):
d = Progress()
time.sleep(2)
for k in range(10):
d.next('number %d'%k)
time.sleep(0.5)
d.next('done.')
while d.alive:
time.sleep(0.1)
d.end()