Tkinter: ProgressBar with indeterminate duration

20,181

Once the mainloop is active, the script wont move to the next line until the root is destroyed. There could be other ways to do this, but I would prefer doing it using threads.

Something like this,

import Tkinter
import ttk
import time
import threading

#Define your Progress Bar function, 
def task(root):
    ft = ttk.Frame()
    ft.pack(expand=True, fill=Tkinter.BOTH, side=Tkinter.TOP)
    pb_hD = ttk.Progressbar(ft, orient='horizontal', mode='indeterminate')
    pb_hD.pack(expand=True, fill=Tkinter.BOTH, side=Tkinter.TOP)
    pb_hD.start(50)
    root.mainloop()

# Define the process of unknown duration with root as one of the input And once done, add root.quit() at the end.
def process_of_unknown_duration(root):
    time.sleep(5)
    print 'Done'
    root.destroy()

# Now define our Main Functions, which will first define root, then call for call for "task(root)" --- that's your progressbar, and then call for thread1 simultaneously which will  execute your process_of_unknown_duration and at the end destroy/quit the root.

def Main():
    root = Tkinter.Tk()
    t1=threading.Thread(target=process_of_unknown_duration, args=(root,))
    t1.start()
    task(root)  # This will block while the mainloop runs
    t1.join()

#Now just run the functions by calling our Main() function,
if __name__ == '__main__':
    Main()

Let me know if that helps.

Share:
20,181
Rickson
Author by

Rickson

Updated on February 04, 2020

Comments

  • Rickson
    Rickson about 4 years

    I would like to implement a progress bar in Tkinter which fulfills the following requirements:

    • The progress bar is the only element within the main window
    • It can be started by a start command without the need of pressing any button
    • It is able to wait until a task with unknown duration is finished
    • The indicator of the progress bar keeps moving as long as the task is not finished
    • It can be closed by a stop command without the need of pressing any stop bar

    So far, I have the following code:

    import Tkinter
    import ttk
    import time
    
    def task(root):
        root.mainloop()
    
    root = Tkinter.Tk()
    ft = ttk.Frame()
    ft.pack(expand=True, fill=Tkinter.BOTH, side=Tkinter.TOP)
    pb_hD = ttk.Progressbar(ft, orient='horizontal', mode='indeterminate')
    pb_hD.pack(expand=True, fill=Tkinter.BOTH, side=Tkinter.TOP)
    pb_hD.start(50)
    root.after(0,task(root))
    time.sleep(5) # to be replaced by process of unknown duration
    root.destroy()
    

    Here, the problem is that the progress bar does not stop after the 5s are over.

    Could anybody help me finding the mistake?

  • Rickson
    Rickson over 9 years
    The status bar will afterwards be integrated into the main program and sys.exit() would close the main program as well. The only problem now is that the code above opens a new Tkinter window containing the status bar which will not be closed after the status bar stops. The code itself running through without errors.
  • Md. Mohsin
    Md. Mohsin over 9 years
    I don't understand. The solution is quite simple. But I would need your help understanding better. There are only 3 functions. 1) ProgressBar, 2) process_of_unkown_duration, 3) Destroy Progressbar. .... Or is there a 4th function as well? Whatever is the case. When would you like to execute sys.exit()? Immediately after progressbar is closed? Or Wait for another function to excecute and then do sys.exit()?
  • Rickson
    Rickson over 9 years
    Well, the code above has to open a new window to be able to show the status bar. But that window has to be closed again if the status bar has stopped. sys.exit() could be executed after process_of_unknown_duration is finished.
  • Md. Mohsin
    Md. Mohsin over 9 years
    and what is the problem in adding sys.exit() below root.destroy()? This is what I understand. 1) Script Starts 2) Your function(process_of_unknown_duration) starts 3) Simultaenously progress bar starts 4) process_of_unknown_duration ends 5) Immediately progressbar is destroyed. ... Now there is nothing left... so what is the issue in adding sys.exit() after root.destroy().... the script is any way completed!! What am I missing?