[Pythonmac-SIG] Threading with Tkinter on OSX - Bus Error
Tony Lownds
tony@lownds.com
Sat, 20 Jul 2002 12:36:36 -0700
Hi Peter,
>I know that some people have previously mentioned that Tk needs to
>have all GUI stuff on one thread, but in the example below, that is
>the case
I don't think it is the case. When your program gets to
time.sleep(3), it's not in the main thread; the next line calls
delegate.message("testing"), which ends up calling Tk.
Calling Tk from a Python-created thread that Tk knows nothing about
on Aqua Tkinter causes crashes to ensue.
>Any help would be greatly appreciated!
Here is your script adjusted to use a Queue. This way the GUI calls
really only happen in one thread. I wish I had a more general
solution.
-Tony
# --------------------------------------------------------------------------
# -- buserr.py -------------------------------------------------------------
from Tkinter import *
from threading import *
import time
import Queue
# Class frm ----------------------------------------------------------------
class frm(Frame):
# Builtins ---------------------------------------------------------
def __init__(self, parent=None):
self.queue = Queue.Queue(10)
Frame.__init__(self, master=parent)
if ((parent.__class__ == Toplevel) or
(parent.__class__ == Tk)):
parent.title("Testing")
parent.geometry("400x300")
self.pack()
self.__createGUI()
# Start the message thread
msgTh = Thread(target=msgThread, args=(self,))
msgTh.start()
# Public Interface --------------------------------------------------
def message(self, msg):
"""Add the given message to the text; may fail with "Full" """
self.queue.put((self.__message, msg))
def runloop(self):
"""similar to mainloop, but also checks our Queue"""
while 1:
try:
dispatch = self.queue.get_nowait()
except Queue.Empty:
root.tk.dooneevent()
else:
apply(dispatch[0], dispatch[1:])
# Private Methods ---------------------------------------------------
def __createGUI(self):
"""Create all the GUI components"""
self.txtFoo = Text(self)
self.txtFoo.pack(side=TOP, fill=X, expand=1, padx=10)
def __message(self, msg):
"""Add the given message to the text"""
currText = self.txtFoo.get(1.0, END)
newText = currText + msg
print "About to explode..."
self.txtFoo.insert(END, newText)
print "We never get here!"
# Thread routine ------------------------------------------------------------
def msgThread(delegate):
time.sleep(3)
delegate.message("Testing")
# Main ----------------------------------------------------------------------
root = Tk()
gui = frm(root)
gui.runloop()