Hello all,
I'm new to wxPython and using it to launch a GUI from a Twisted Python
process. It's a slightly backwards arrangement where the twisted
process runs as a daemon but pops up a dialog box every now and again.
Because twisted is asynchronous, we are forced to run the wxPython app
in a thread to avoid the event loop stalling while the GUI is open.
Initially this approach seems to work, but I've discovered a problem
that is related to running in a thread is this manner:
The GUI we create has a wx.TextCtrl with style=wx.TE_MULTILINE. On my
Mac, a side-effect of using the multiline widget is that the spell
checker is invoked on the contents, by default as characters are
added. When running in a thread, this step locks up the GUI before
eventually producing the error "Alert: Couldn't contact Spell
Checker".
Confoundingly, it only seems to have the problem if a value is set
programmatically for the TextCtrl -- i.e. via the value kwarg during
contruction or via a call to SetValue. If you don't set an initial
value and just type in the box, the spell checker is invoked
successfully.
I've included a testcase that demonstrates these problems, but I also
want to ask a couple of questions. First and foremost, is it
reasonable to be running a wxPython app inside a thread like this?
Secondly, if this is just a special case, is there a way to
programatically disable spellchecking on a multiline TextCtrl?
I'm running the default Leopard installation of wxPython (2.8.4.0) on
Python 2.5. The problem seems specific to OS X. I've run the attached
testcase with 2.8.x on Windows and Ubuntu, both Python2.5, without
issue.
Many thanks,
Matt.
···
-------------
testcase.py
#!/usr/bin/python
from threading import Thread
import wx
class GUI(wx.Frame):
def __init__(self, id, title, size=None):
#create frame
wx.Frame.__init__(self, None, id, title, size=size)
#parent panel & layout
panel = wx.Panel(self, -1)
vbox = wx.BoxSizer(wx.VERTICAL)
#data
label = "What is the Answer to Life, the Universe &
Everything?"
initial_value = "Hint: it's between 41 and 43"
#generate components
label = wx.StaticText(panel, -1, label)
#this errors in threaded case:
textarea = wx.TextCtrl(panel, -1, value=initial_value,
style=wx.TE_MULTILINE)
#this also errors in threaded case:
#textarea = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)
#textarea.SetValue(initial_value)
#this works in threaded case:
#textarea = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)
#build layout
box = wx.BoxSizer(wx.VERTICAL)
box.Add(label, 0, wx.BOTTOM, 3)
box.Add(textarea, 1, wx.EXPAND)
#add to parent layout
vbox.Add(box, 1, wx.EXPAND | wx.ALL, 10)
#end spacer
vbox.Add((-1, 15))
#apply parent layout; center'n'show
panel.SetSizer(vbox)
self.Centre()
self.Show(True)
class ThreadedGUI(Thread):
def __init__ (self):
Thread.__init__(self)
def run(self):
app = wx.App()
GUI(-1, 'Spell Check Test - Threaded', size=(500, 600))
app.MainLoop()
if __name__ == '__main__':
NORMAL = 100
INTHREAD = 101
CASE = INTHREAD
if CASE is NORMAL:
app = wx.App()
GUI(-1, 'Spell Check Test', size=(500, 600))
app.MainLoop()
elif CASE is INTHREAD:
threaded = ThreadedGUI()
threaded.start()