Progress bar in tkinter not working
I compacted the loading bar I got working in an older project of mine. The only way I had figured it out was to call the progress bar handling calls in a new thread and call the work-intensive functions from this thread into another new thread.
It is bad practice to have a separate threads handling UI elements other than the UI thread, including starting and stopping a progress bar; however it does work and I've been using this project to do pretty heavy processing with zero issues for months now.
Here the progress bar is working in a small script, using Python 3.5.2 on W10 64-Bit
from tkinter import *import tkinter.ttk as ttkimport threadingimport timeclass Main_Frame(object): def __init__(self, top=None): # save root reference self.top = top # set title bar self.top.title("Loading bar example") # start button calls the "initialization" function bar_init, you can pass a variable in here if desired self.start_button = ttk.Button(top, text='Start bar', command=lambda: self.bar_init(2500)) self.start_button.pack() # the progress bar will be referenced in the "bar handling" and "work" threads self.load_bar = ttk.Progressbar(top) self.load_bar.pack() # run mainloop self.top.mainloop() def bar_init(self, var): # first layer of isolation, note var being passed along to the self.start_bar function # target is the function being started on a new thread, so the "bar handler" thread self.start_bar_thread = threading.Thread(target=self.start_bar, args=(var,)) # start the bar handling thread self.start_bar_thread.start() def start_bar(self, var): # the load_bar needs to be configured for indeterminate amount of bouncing self.load_bar.config(mode='indeterminate', maximum=100, value=0) # 8 here is for speed of bounce self.load_bar.start(8) # start the work-intensive thread, again a var can be passed in here too if desired self.work_thread = threading.Thread(target=self.work_task, args=(var,)) self.work_thread.start() # close the work thread self.work_thread.join() # stop the indeterminate bouncing self.load_bar.stop() # reconfigure the bar so it appears reset self.load_bar.config(value=0, maximum=0) def work_task(self, wait_time): for x in range(wait_time): time.sleep(0.001)if __name__ == '__main__': # create root window root = Tk() # call Main_Frame class with reference to root as top Main_Frame(top=root)