How to run a function in the background of tkinter

You will find the answer in this other question Tkinter locks python when Icon loaded and tk.mainloop in a thread.

In a nutshell, you need to have two threads, one for tkinter and one for the background task.


Event based programming is conceptually simple. Just imagine that at the end of your program file is a simple infinite loop:

while <we have not been told to exit>:
    <pull an event off of the queue>
    <process the event>

So, all you need to do to run some small task continually is break it down into bite-sized pieces and place those pieces on the event queue. Each time through the loop the next iteration of your calculation will be performed automatically.

You can place objects on the event queue with the after method. So, create a method that increments the number, then reschedules itself to run a few milliseconds later. It would look something like:

def add_one(self):
    self.counter += 1
    self.after(1000, self.add_one)

The above will update the counter once a second. When your program initializes you call it once, and from then after it causes itself to be called again and again, etc.

This method only works if you can break your large problem (in your case "count forever") into small steps ("add one"). If you are doing something like a slow database query or huge computation this technique won't necessarily work.


I don't have sufficient reputation to comment on Bryan Oakley's answer (which I found to be very effective in my program), so I'll add my experience here. I've found that depending on how long your background function takes to run, and how precise you want the time interval to be, it can be better to put self.after call at the beginning of the recurring function. In Bryan's example, that would look like

def add_one(self):
    self.after(1000, self.add_one)
    self.counter += 1

Doing it this way ensures that the interval of time is respected exactly, negating any interval drift that might occur if your function takes a long time.


Try to understand this example : clock updating in backgroud, and updating GUI ( no need for 2 threads ).

# use Tkinter to show a digital clock
# tested with Python24    vegaseat    10sep2006
from Tkinter import *
import time
root = Tk()
time1 = ''
clock = Label(root, font=('times', 20, 'bold'), bg='green')
clock.pack(fill=BOTH, expand=1)
def tick():
    global time1
    # get the current local time from the PC
    time2 = time.strftime('%H:%M:%S')
    # if time string has changed, update it
    if time2 != time1:
        time1 = time2
        clock.config(text=time2)
    # calls itself every 200 milliseconds
    # to update the time display as needed
    # could use >200 ms, but display gets jerky
    clock.after(200, tick)
tick()
root.mainloop(  )

credits: link to site

Tags:

Python

Tkinter