0

I am using the tkinter GUI package in python and would like to track the progress of a process that loops through a list and does something for each item on the list. I want to track the progress in a label that displays "Item 1 of 100 processed." The label is bound to a String Variable. Here was what I tried originally:

def runLoop(self):
    for site in self.sitelist:
        #Do stuff
        self.x+=1
        self.outLabelStrVar="Item " + str(self.x) + " of " + str(len(self.sitelist)) + " processed."

However, this of course did not update in real time, because I never returned to the tkinter window mainloop, as is suggested in threads like this one.

So I updated my code to make the function recursive:

def runLoop(self, item=None):
     if item is None:
         for site in self.sitelist:
             self.after(1,runLoop(site))
     else:
         self.x+=1
         self.outLabelStrVar="Item " + str(self.x) + " of " + str(len(self.sitelist)) + " processed."

Which I thought would return to the main tkinter loop with each iteration of the for loop. But this also doesn't update the output label in real time.

What am I misunderstanding?

Maile Cupo
  • 636
  • 1
  • 10
  • 26
  • I don't see any `StringVar` in the code, are you using one for the `textvariable` of the label? (see https://stackoverflow.com/questions/46981834/tkinter-label-textvariable-not-changing) – j_4321 Jul 13 '18 at 13:56
  • 3
    `self.after(1,runLoop(site))` calls `runLoop()` RIGHT NOW (causing the exact same problem as before), then 1 millisecond later does nothing whatsoever (since `runLoop()` returns None, and that's what you're actually passing to `after()`). You need to write this as `self.after(1, runLoop, site)` to actually defer the function call. – jasonharper Jul 13 '18 at 13:57
  • @jasonharper Thanks, your response included the information I needed to update my code so it would work. I think I was mainly misunderstanding the after method. Though actually I'm still confused, if the #do stuff code interacts with the web (it does), I might not want to just run it in intervals looping through the list. How do I wait until one loop is finished to start the next? – Maile Cupo Jul 13 '18 at 14:05
  • If each item takes a tiny amount of time to process, you'd probably want to schedule one at first, and then at the end of that processing, schedule the next (rather than scheduling them all at once). If the items may take significant time to process, you'd need to run them in a separate thread to keep the GUI responsive. – jasonharper Jul 13 '18 at 16:04

0 Answers0