Search code examples
pythontkinterttk

Show ttk progressbar (python) while running a function


I am having troubles with my code. What I try to do is show a ttk indeterminate progress bar while function ToDo() is running. I've been searching on the internet and I found some posts but in them people launch their function from a tk button while my goal is to launch it from outside tk window. Here's my try, it runs my function ToDo() but doesn't show the progressbar. Do I need to use threading? If so, how should I use it? I'm new at python...

try:
    import tkinter as tk
    from tkinter import ttk
except ImportError:
    import Tkinter as tk
    import ttk
import time

def ToDo():
    time.sleep(1)
    print("1 sec")
    time.sleep(1)
    print("2 sec")
    time.sleep(1)
    print("3 sec")
    time.sleep(1)
    print("4 sec")
    time.sleep(1)
    print("5 sec")
    global variable_check_final
    variable_check_final = True


class Application(tk.Frame):
    def __init__(self, main_window):
        # super().__init__(main_window)
        tk.Frame.__init__(self)
        main_window.title("Please wait")

        self.progressbar = ttk.Progressbar(self, mode="indeterminate")
        self.progressbar.pack()
        self.progressbar.place(x=30, y=60, width=200)
        self.place(width=200, height=200)
        main_window.geometry("300x200")
        self.progressbar.start()
        self.checkfinal()
        ToDo()


    def checkfinal(self):
        if variable_check_final == True:
            self.progressbar.stop()
            main_window.destroy()
        else:
            print("not yet")
            self.after(1000, self.checkfinal)



if __name__ == "__main__":
    print("started")
    global variable_check_final
    variable_check_final = False
    main_window = tk.Tk()
    app = Application(main_window)
    app.mainloop()

Solution

  • sleep will stop the whole program for your required time and will not allow you to update your progress bar. So make a function that contains a while loop which will run for your required time and update the window:

    def Sleep(t, func):
        t1 = time.time()
        while time.time()-t1 < t:
            func()
    

    t is the time and func is the function you will give as input and it will run. To update you can use like:

    Sleep(1, main_window.update)
    

    Here is a complete working code:

    try:
        import tkinter as tk
        from tkinter import ttk
    except ImportError:
        import Tkinter as tk
        import ttk
    import time
    
    def Sleep(t, func):
        t1 = time.time()
        while time.time()-t1 < t:
            func()
    def ToDo():
        Sleep(1, main_window.update)
        print("1 sec")
        Sleep(1, main_window.update)
        print("2 sec")
        Sleep(1, main_window.update)
        print("3 sec")
        Sleep(1, main_window.update)
        print("4 sec")
        Sleep(1, main_window.update)
        print("5 sec")
        global variable_check_final
        variable_check_final = True
    
    
    class Application(tk.Frame):
        def __init__(self, main_window):
            # super().__init__(main_window)
            tk.Frame.__init__(self)
            main_window.title("Please wait")
            self.progressbar = ttk.Progressbar(self, mode="indeterminate")
            self.progressbar.place(x=30, y=60, width=200)
            self.place(width=200, height=200)
            main_window.update()
            main_window.geometry("300x200")
            self.progressbar.start()
            self.checkfinal()
            ToDo()
    
    
        def checkfinal(self):
            if variable_check_final == True:
                self.progressbar.stop()
                main_window.destroy()
            else:
                print("not yet")
                self.after(1000, self.checkfinal)
    
    
    
    if __name__ == "__main__":
        print("started")
        global variable_check_final
        variable_check_final = False
        main_window = tk.Tk()
        app = Application(main_window)
        app.mainloop()