Adler Müller
Adler Müller

Reputation: 248

Progressbar starts after print statements

Why is the progressbar starting after the print-commands?

I want to start the progressbar first. And wenn the 2nd print command ("After the sleep statement") was excecuted, I want to stop the progressbar. Any ideas?

from tkinter import Tk 
from tkinter.ttk import Progressbar 
import time

# root window 
root = Tk() 
root.geometry('300x120') 
root.title('Progressbar Demo')

root.grid()

# progressbar 
pb = Progressbar(
    root,
    orient='horizontal',
    mode='indeterminate',
    length=280 )

# place the progressbar 
pb.grid(column=0, row=0, columnspan=2, padx=10, pady=20)

pb.start()



print("Before the sleep statement")
time.sleep(5)
print("After the sleep statement")

# pb.stop()

root.mainloop()

The current problem is that the progressbar is only started after time.sleep command.

Upvotes: 0

Views: 105

Answers (2)

Kaz
Kaz

Reputation: 1177

The progress bar and all graphical elements of tkinter are launched from main loop (root.mainloop()). So, sleeping is done before the main loop. If you want so, you should implement spleeping IN main loop.

Furthermore, for a non-instantaneous processing, it's recommended to use a separate thread (e.g. with threading.Tread) to avoid blocking the GUI thread.

You can do something like this :

import threading
import time

from tkinter import Tk, Button
from tkinter.ttk import Progressbar


# root window
root = Tk()
root.geometry('300x120')
root.title('Progressbar Demo')

root.grid()

# progressbar
pb = Progressbar(root, orient='horizontal', mode='indeterminate', length=280)
# place the progressbar
pb.grid(column=0, row=0, columnspan=2, padx=10, pady=20)

def statement():
    pb.start()
    print("Before the sleep statement")
    time.sleep(5)
    print("After the sleep statement")
    pb.stop()

button = Button(root, text="Start", command=lambda: threading.Thread(target=statement).start())
button.grid(column=0, row=1)

root.mainloop()

Upvotes: 2

TheLizzard
TheLizzard

Reputation: 7680

@Kaz's answer without the need for the button:

import threading
import time

from tkinter import Tk, Button
from tkinter.ttk import Progressbar


# root window
root = Tk()
root.geometry('300x120')
root.title('Progressbar Demo')

# progressbar
pb = Progressbar(root, orient="horizontal", length=280)
pb.grid(column=0, row=0, columnspan=2, padx=10, pady=20)

def statement():
    global stop_the_progressbar
    print("Before the sleep statement")
    time.sleep(5)
    print("After the sleep statement")
    stop_the_progressbar = True

def tkinter_loop():
    if stop_the_progressbar:
        pb.stop()
    else:
        root.after(100, tkinter_loop)

# Start the progressbar
pb.start()
threading.Thread(target=statement, daemon=True).start()
stop_the_progressbar = False
tkinter_loop()

root.mainloop()

It uses a .after loop to check if the progressbar should be stopped. Look at this for more details on how .after works. Also please note that you shouldn't call any tkinter methods from the new thread.

This example doesn't run well on IDLE because of a bug in IDLE. The text "Before the sleep statement" will be printed after the thread stops but it actually runs at the correct time.

Upvotes: 3

Related Questions