Search code examples
pythonprogress-barttk

Filling a Progress Bar without a button


so I'm trying to make a progress bar that automatically starts filling when the window is opened.. so instead of making a button that when pressed it call the function of filling the bar I call the function directly, and unexpectedly for me it shows an empty window and after 5 sec (the time to fill the bar) the bar shows filled the thing is that when I replaced the fill() with a button it works properly so why isn't it working just by calling the function and how to make it fill without a button my code:

from tkinter import *
from tkinter import ttk as ttk
from time import *

def fill():
    t = 100
    x = 0
    s = 1
    while x <= t:
        bar['value'] += s
        x += s
        sleep(0.05)
        window2.update_idletasks()


def read():

    global window2
    window2 = Tk()

    global bar
    bar = ttk.Progressbar(window2,orient=HORIZONTAL,length=300)
    bar.pack(pady=15)

    fill()       # here I replace the function with a button calling it and it works well but I don't want a button

    window2.mainloop()

read()


Solution

  • Your problem is caused by the use of time.sleep in tkinter.

    Instead use the after scheduler.

    The following code modification with comments shows one way to implement it.

    from tkinter import *
    from tkinter import ttk as ttk
    
    def fill(s, c):
        c = c + 1
        # Update progressbar
        bar['value'] = c
        # Test for exit conditions
        if c <= s:
            # Repeat action recursively by passing current values back to itself
            window2.after(50, fill, s, c)
        else:
            bar.destroy()
            # Ready to continue creating other widgets
    
    def read():
    
        global window2
        window2 = Tk()
    
        global bar
    
        delay, steps, count = 50, 100, 0
    
        # Include the maximum step value `steps` for given length
        bar = ttk.Progressbar(window2, orient = HORIZONTAL, length = 300, maximum = steps)
        bar.pack(pady=15)
        # Begin by using `after` scheduler with `delay` to pass `steps` and `count` to `fill` function
        window2.after(delay, fill, steps, count)
    
        window2.mainloop()
    
    read()