pythontkinterprogress-bar

tkinter progress bar freezes in I do anything else


I built a simple progress bar (I want to use it in many other programs), but the problem is, if I move the window, or click on anything else the progress window freezes. The script keeps running but the progress window has "Not Responding" and does not update.

from tkinter import *
from tkinter.ttk import *
from datetime import *
import time

def main():
    # get start time to calc execution time
    start_time = datetime.now().replace(microsecond=0)
    print(start_time, "\n")

    GB = 100
    window = Tk()
    percent = StringVar()
    text = StringVar()
    fleft = StringVar()
    download = 0
    speed = 5

    percentLabel = Label(window, textvariable=percent).pack()
    taskLabel = Label(window, textvariable=text).pack()
    leftLabel = Label(window, textvariable=fleft).pack()


    bar = Progressbar(window,orient=HORIZONTAL,length = 300)
    bar.pack(pady=10)


    while (download < GB):
        download += speed
        time.sleep(1)
        bar['value']+=(speed/GB)*100
        percent.set(str(int((download/GB)*100))+"%")
        text.set(str(download)+" files completed!")
        fleft.set(str(int(GB - download)) + " left to complete.")
        window.update_idletasks()
    window.mainloop()

if __name__ == '__main__':
    main()

Solution

  • It is not recommended to use loop and time.sleeep() in the main thread of tkinter application as they will block the tkinter mainloop from updating pending updates and events.

    Use .after() to simulate the loop instead:

    from tkinter import *
    from tkinter.ttk import *
    from datetime import *
    import time
    
    def main():
        # get start time to calc execution time
        start_time = datetime.now().replace(microsecond=0)
        print(start_time, "\n")
    
        GB = 100
        window = Tk()
        percent = StringVar()
        text = StringVar()
        fleft = StringVar()
        download = 0
        speed = 5
    
        percentLabel = Label(window, textvariable=percent).pack()
        taskLabel = Label(window, textvariable=text).pack()
        leftLabel = Label(window, textvariable=fleft).pack()
    
    
        bar = Progressbar(window,orient=HORIZONTAL,length = 300)
        bar.pack(pady=10)
    
    
        def update_progress(download):
            progress = round((download / GB) * 100, 0)
            bar['value'] = progress
            percent.set(f'{progress:.0f}%')
            text.set(f'{download} files completed!')
            fleft.set(f'{GB-download} left to complete.')
            if download < GB:
                window.after(1000, update_progress, download+speed)
    
        update_progress(download) # start the after loop
        window.mainloop()
    
    if __name__ == '__main__':
        main()