Tkinter managing my event loops alongside my mainloop Tkinter managing my event loops alongside my mainloop tkinter tkinter

Tkinter managing my event loops alongside my mainloop


You already have an infinite loop running, so you shouldn't be trying to add another one. Instead, you can use the after method to cause a function to be repeatedly called every so often. In your case, you can replace this:

def updateStock(self):   while True:        labelName = str(s) + "Label"        stockPrice = get_quote(s)        self.labelName = Label(self.myContainer1, text = s.upper() + ": " + str(stockPrice))        self.labelName.pack()        time.sleep(10)

... with this:

def updateStock(self):    labelName = str(s) + "Label"    stockPrice = get_quote()    self.labelName = Label(self.myContainer1, text = s.upper() + ": " + str(stockPrice))    self.labelName.pack()    self.after(10000, self.updateStock)

This will get a quote, add a label, then arrange for itself to be called again in 10 seconds (10,000 ms).

However, I doubt that you want to create a new label every 10 seconds, do you? Eventually the window will fill up with labels. Instead, you can create a label once, then update the label in each iteration. For example, create self.label once in the init, then in the loop you can do:

self.labelName.configure(text=s.upper() + ": " + str(stockPrice))


You are looking for threading.Put the event you want to run in another thread. See this example:

import thread, timedef myfunc(a1,a2):    while True:      print a1,a2      time.sleep(1)thread.start_new_thread(myfunc,("test","arg2")tkroot.mainloop()

Now you have a function running along with the Tkinter window that prints the args every second.

EDIT: I don't know why so many down votes. Tkinter DOES work well with threads, I've already used this trick several times without problems. See this example:

Download a 10 MB file and log the progress to a Tkinter window.

Without threading:

import urllib2,threadimport Tkinter as tkclass Example(tk.Frame):    def __init__(self, parent):        tk.Frame.__init__(self, parent)           self.parent = parent                self.initUI()    def initUI(self):        self.pack(fill=tk.BOTH, expand=1)        canvas = tk.Canvas(self)        self.text = canvas.create_text(18,18,anchor=tk.W,font="Purisa",text="Status: Press start to download...")        but=tk.Button(text="Start",command=self.start)        canvas.create_window((270,18),window=but)        canvas.pack(fill=tk.BOTH, expand=1)        self.canvas=canvas    def start(self):        #thread.start_new_thread(        self.download("http://ipv4.download.thinkbroadband.com/10MB.zip","10mb.zip")        #)    def onEnd(self):            self.canvas.itemconfig(self.text, text="Status: done!")    def download(self,url,file_name):        u = urllib2.urlopen(url)         f = open(file_name, 'wb')        meta = u.info()        file_size = int(meta.getheaders("Content-Length")[0])        print "Downloading: %s Bytes: %s" % (file_name, file_size)        file_size_dl = 0        block_sz = 1024*50 #50 kb        while True:            buffer = u.read(block_sz)            if not buffer:                break            file_size_dl += len(buffer)            f.write(buffer)            status = r"[%3.2f%%]" % (file_size_dl * 100. / file_size)            self.canvas.itemconfig(self.text,text="Status: downloading..."+status)        f.close()        self.onEnd()def main():    root = tk.Tk()    root.resizable(0,0)    ex = Example(root)    root.geometry("300x70")    root.mainloop()  main()

The window freezes till the download is done.

With thread:

import urllib2,threadimport Tkinter as tkclass Example(tk.Frame):    def __init__(self, parent):        tk.Frame.__init__(self, parent)           self.parent = parent                self.initUI()    def initUI(self):        self.pack(fill=tk.BOTH, expand=1)        canvas = tk.Canvas(self)        self.text = canvas.create_text(18,18,anchor=tk.W,font="Purisa",text="Status: Press start to download...")        but=tk.Button(text="Start",command=self.start)        canvas.create_window((270,18),window=but)        canvas.pack(fill=tk.BOTH, expand=1)        self.canvas=canvas    def start(self):        thread.start_new_thread(        self.download("http://ipv4.download.thinkbroadband.com/10MB.zip","10mb.zip")        )    def onEnd(self):            self.canvas.itemconfig(self.text, text="Status: done!")    def download(self,url,file_name):        u = urllib2.urlopen(url)         f = open(file_name, 'wb')        meta = u.info()        file_size = int(meta.getheaders("Content-Length")[0])        print "Downloading: %s Bytes: %s" % (file_name, file_size)        file_size_dl = 0        block_sz = 1024*50 #50 kb        while True:            buffer = u.read(block_sz)            if not buffer:                break            file_size_dl += len(buffer)            f.write(buffer)            status = r"[%3.2f%%]" % (file_size_dl * 100. / file_size)            self.canvas.itemconfig(self.text,text="Status: downloading..."+status)        f.close()        self.onEnd()def main():    root = tk.Tk()    root.resizable(0,0)    ex = Example(root)    root.geometry("300x70")    root.mainloop()  main()

Doesn't freeze and the text is updated normally.