Search code examples
pythonpython-3.xtkinterttk

Issue with progress bar thread


I created a small GUI using Tkinter. It has a button on click of which some data is written to Excel.

To show the progress, I added a progress bar but since the process is resource intensive, the progress bar appears only at the end. Therefore, I used threading as shown.

In the Main function below, I initialized the progress bar in a different thread but I want to update the current value of the task in Start function.

Because of this line:

progressbar.Start()

it is just continuously running without anything to do with the current progress.

def Start():
    x = 0
    progressbar["value"] = x
    for idx, val in enumerate(rows):
      region_url = val[1]

      if (model_url != '-'):
        url = 'http://testurl/' + region_url 

        x = x + 1
        if (x > 4):
            break

# Main          
if __name__ == '__main__': 
    window = Tk()
    new = progress(window)

    # Add a grid
    mainframe = Frame(window)
    mainframe.grid(column=0,row=0, sticky=(N,W,E,S) )
    mainframe.columnconfigure(0, weight = 1)
    mainframe.rowconfigure(0, weight = 1)
    mainframe.pack(pady = 100 , padx = 150)

    # DropDown
    popupMenu = OptionMenu(mainframe, tkvar, *regionList)
    Label(mainframe, text="Region").grid(row = 1, column = 0)

    # Button
    btnSubmit = Button(mainframe, text= "Execute",command=StartScrap).grid(row = 2, column = 18)
    popupMenu.grid(row = 2, column =0)

    # Progress Bar
    progressbar = ttk.Progressbar(window, orient = HORIZONTAL,length=300, mode = 'indeterminate')
    progressbar.pack()
    t = threading.Thread()
    progressbar["maximum"] = 4
    progressbar.start()
    window.mainloop()

Solution

  • There are a couple things in your code that needs fixing.

    Firstly you defined the function Start which controls how your progressbar is updated, but you never call it.

    Secondly, you define the progressbar mode as indeterminate and that just start the progress bar - it works but it will just periodically move the progressbar.

    Thirdly, you defined the Thread t but never put a target function.

    Here's how to move your progressbar in a thread:

    from tkinter import *
    from tkinter import ttk
    import threading
    import time
    
    def Start():
        def update_pbar():
            for i in range(5): #replace this with your method to update your progressbar
                time.sleep(1)
                progressbar["value"] = i
        t = threading.Thread(target=update_pbar)
        t.start()
    
    # Main
    if __name__ == '__main__':
        window = Tk()
    
        progressbar = ttk.Progressbar(window, orient = HORIZONTAL,length=300, mode = 'determinate')
        progressbar.pack()
        progressbar["maximum"] = 4
        btnSubmit = Button(window, text="Execute", command=Start).pack()
        window.mainloop()