469,332 Members | 7,043 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,332 developers. It's quick & easy.

Problems with Tkinter and threads

My Tkinter application has to receive events from a TCP connection. I
have chosen to do this in the following manner:

The TCP communication takes place in a separate thread. When I receive
data, I generate an event in the Python application thus:

app.event_generate("<<myevent1>>")

In the associated event handler, I do this:

self.label1.grid_forget()
self.label2.grid()

This works well if event is generated from a function that is called
through the after() method of the main frame. But when I send the event
from my TCP thread, the system hangs in the call to grid_forget.

Surprisingly, if I replace self.label1.grid_forget() with
self.label1.destroy(), things work well.

What can I do to call grid_forget in this event handler?

--
Claus Tondering

Jul 17 '06 #1
6 3347
"Claus Tondering" <cl*************@gmail.comwrites:
The TCP communication takes place in a separate thread. When I receive
data, I generate an event in the Python application thus:

app.event_generate("<<myevent1>>")
I think all bets are off when you do that. Tkinter is simply not
thread safe and generating events from another thread can trigger race
conditions and who knows. You need to self-generate events in the
gui thread with (e.g.) Tk.after, and have those events check for news
from the TCP thread. You could do that with a semaphore, or more
pythonically with a Queue.
Jul 17 '06 #2
Paul Rubin wrote:
Tkinter is simply not
thread safe and generating events from another thread can trigger race
conditions and who knows.
Does this mean that I cannot even call the main thread's after_idle
method from another thread?

--
Claus Tondering

Jul 17 '06 #3
"Claus Tondering" <cl*************@gmail.comwrites:
Does this mean that I cannot even call the main thread's after_idle
method from another thread?
I'm not certain, I've never tried it that way since there's no way I
could be confident of its reliability even if it appeared to work.
Just use after_idle to check for a Queue item and set another
after_idle event. I generally use about 50 msec (20 hz) which doesn't
cause any noticable delay for a gui. Call the first after_idle from
the gui thread when you put up the gui.
Jul 17 '06 #4
On Mon, 17 Jul 2006 12:58:08 +0200, Claus Tondering
<cl*************@gmail.comwrote:
My Tkinter application has to receive events from a TCP connection. I
have chosen to do this in the following manner:

The TCP communication takes place in a separate thread. When I receive
data, I generate an event in the Python application thus:

app.event_generate("<<myevent1>>")
This is where the problem is: if you do just a event_generate without
specifying the 'when' option, the binding is fired immediately in the
current thread. To be sure that an event is created and that the thread
switch actually happens, do:

app.event_generate("<<myevent1>>", when='tail')

and things should work fine.

HTH
--
python -c "print ''.join([chr(154 - ord(c)) for c in
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"
Jul 17 '06 #5
Eric Brunel wrote:
This is where the problem is: if you do just a event_generate without
specifying the 'when' option, the binding is fired immediately in the
current thread. To be sure that an event is created and that the thread
switch actually happens, do:

app.event_generate("<<myevent1>>", when='tail')

and things should work fine.
Nice!

Obviously, there are important things that I don't know about Tkinter.
Unless I'm much mistaken, neither Fredrik Lundh's "An Introduction to
Tkinter" nor John W. Shipman's "Tkinter reference: a GUI for Python"
mentions the when='tail' option.

--
Claus Tondering

Jul 17 '06 #6
On Mon, 17 Jul 2006 15:20:46 +0200, Claus Tondering
<cl*************@gmail.comwrote:
Eric Brunel wrote:
>This is where the problem is: if you do just a event_generate without
specifying the 'when' option, the binding is fired immediately in the
current thread. To be sure that an event is created and that the thread
switch actually happens, do:

app.event_generate("<<myevent1>>", when='tail')

and things should work fine.

Nice!

Obviously, there are important things that I don't know about Tkinter.
Unless I'm much mistaken, neither Fredrik Lundh's "An Introduction to
Tkinter" nor John W. Shipman's "Tkinter reference: a GUI for Python"
mentions the when='tail' option.
The ultimate documentation is unfortunately still the tcl/tk man pages.
There is an on-line version here:

http://www.tcl.tk/man/

Once you've understood how to convert the tcl syntax to Python/Tkinter,
it's always the most up-to-date source of information.

HTH
--
python -c "print ''.join([chr(154 - ord(c)) for c in
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"
Jul 17 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Julia Goolia | last post: by
3 posts views Thread by Bob Greschke | last post: by
reply views Thread by Bryan Olson | last post: by
2 posts views Thread by Michael Zhang | last post: by
9 posts views Thread by Tuvas | last post: by
1 post views Thread by Michael Yanowitz | last post: by
14 posts views Thread by Hendrik van Rooyen | last post: by
2 posts views Thread by Kevin Walzer | last post: by
2 posts views Thread by Kevin Walzer | last post: by
reply views Thread by zhoujie | last post: by
1 post views Thread by haryvincent176 | last post: by
1 post views Thread by Marylou17 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.