1

I know that Python’s Tk interface has some problems when using threads, and I’ve already run into problems with it. My idea is now to use a Queue.Queue to somehow pass events to the Tk mainloop, similarly to the following example.

from Tkinter import *
import Queue
import time

# this queue will be filled by other threads
queue = Queue.Queue()
queue.put("Helloooo!")
queue.put("hi there, everyone!")

class Application(Frame):
    def update(self):
        while True:
            try:
                text = queue.get(False)
                self.hi_there["text"] = text
                time.sleep(3)
            except Queue.Empty:
                self.quit()

    def create_widgets(self):
        self.hi_there = Label(self)
        self.hi_there["text"] = "Hello"

        self.hi_there.pack({"side": "left"})

    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.create_widgets()

root = Tk()
app = Application(master=root)
app.update()
app.mainloop()

Of course, I must not call update myself (this will execute everything before the UI is even shown) but need Tk to handle that during its mainloop.

Is there any foolproof way to accomplish that with Tk which will not break under certain circumstances? Or should I just resort to Qt for that?

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
Debilski
  • 66,976
  • 12
  • 110
  • 133
  • 1
    The answers to this question talk about using the `after()` method to set up a recurring call: http://stackoverflow.com/questions/2400262/code-a-timer-in-a-python-gui-in-tkinter – Thomas K Jul 26 '11 at 12:15
  • One of you just post that as an answer! – agf Jul 26 '11 at 12:58
  • @eryksun: It’s just that I did not know about these methods. – Debilski Jul 26 '11 at 13:16
  • The somehow miserable part in this is that Tcl/Tk handles threads better than Python, so if you did it the other way round you had less problems in theory (via loading tclpython inside a Tcl thread and using the usual thread::send -async api). But well, you can use Tkinter with the after and polling the Queue thing too. works. – schlenk Jul 26 '11 at 17:56

1 Answers1

3

As a general rule of thumb a GUI application should never, ever call sleep, should never have an infinite loop (except for the event loop), and you should never call 'update'. The only exception to never calling update is that is is ok only when you truly understand why you should not.

Create a method that does two things: check the queue, and then use 'after' to call itself after some small period of time. Then, call this method once at the beginning of your program just before starting the event loop, after all other initialization has taken place.

For a working example of such a function, see How to create a timer using tkinter?

Community
  • 1
  • 1
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • I understand. But of course, the `sleep` and recursion methods were meant to live in a separate thread – only this would not work well with Tk. – Debilski Jul 26 '11 at 13:24