Reputation: 458
I have tried to implement a Tkinter progressbar using threading simply to see when a program is running, and to close the progressbar when the program ends.
import tkinter
import ttk
import time
import threading
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()
def process_of_unknown_duration(root):
time.sleep(5)
root.destroy()
def pBar():
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()
if __name__ == '__main__':
pBar()
#some function
My issue is that once the progressbar starts, the program just hangs and wont do anything else. Any hints?
Upvotes: 1
Views: 1476
Reputation: 411
Are you still interested in this problem? Try to use the update()
method for the root object instead of the threading in the simple cases. I offer the following simplified demo-solution with global variables as a start point for subsequent developments.
import tkinter
from tkinter import *
from tkinter import ttk
import time
root1 = Tk()
progrBar1 = None # The main progress bar
win2 = None
def click_but1():
global win2, progrBar2
if win2 is None:
win2 = Toplevel() # Secondary window
win2.title('Secondary')
win2.protocol('WM_DELETE_WINDOW', clickClose) # close the secondary window on [x] pressing
but2 = Button(win2, text='Close', command=clickClose)
but2.pack()
but3 = Button(win2, text='Process', command=clickProcess)
but3.pack()
progrBar2 = ttk.Progressbar(win2, orient = 'horizontal', length = 300, mode = 'determinate')
progrBar2.pack()
if progrBar1:
progrBar1.start(50)
def clickClose():
global win2
progrBar1.stop()
win2.destroy()
win2=None
def clickProcess():
my_func()
def my_func():
global progrBar2
range1, range2 = 20, 40
step1 = 100/range1
for i in range(range1):
for j in range(range2):
time.sleep(0.01)
progrBar2.step(step1)
root1.update() # the "update" method
root1.title('Root') # Main window
progrBar1 = ttk.Progressbar(root1, orient = 'horizontal', mode = 'indeterminate') # The main progress bar
but1 = Button(root1, text = 'Start', command = click_but1)
but1.pack()
progrBar1.pack()
root1.mainloop()
The progress bar in the first (main) window is moving only in the presence of the secondary window. This pogress bar stops and returns to the initial position after closing of the secondary window. The secondary window has it own progress bar for the demo purposes and to show the interaction between windows by means of the update()
method.
Upvotes: 0
Reputation: 703
This is because your call root.mainloop()
is blocking the execution of your code. It basically represents the loop for your UI. You might want to look at this answer for a progress bar that is launched by a button.
Upvotes: 1