Home > database >  Trouble with making a updating loading bar (Label) in Tkinter
Trouble with making a updating loading bar (Label) in Tkinter

Time:04-02

I am making a percentage updating Loading bar(Label) which should automatically start when my program has started. When the 'Loading bar' hits 100%, the 'Loading bar' should be removed, and the rest of the program should continue, although when I am starting the program, the window does not respond until about 5 seconds.

number = 0
number1 = str(number)

Labe = tk.Label(root, width=10,bd=1, bg="#ADA5A5", font=("Arial Bold", 36), fg="White")
Labe.grid(row=0, column=0)

def work():
   global number1
   Labe['text'] = "Loading"   " "   number1   "%"
   global number
   number = number   1
   number1 = str(number)
   if number == 102:
      root.after(1000)
      print("end")
      Labe.grid_remove()

num = 101
for x in range(num):
    print("He")
    root.after(50, work)
    root.after(50)

#Adding stuff to root
rootHelloLabel = tk.Label(root, text="Ordering system, please sign in", bg="#7271AD",
                          fg="White", font=("Arial Bold", 40), width=48, height=2)
placeholder = tk.Label(root, text="", pady=20, bg="#ACAD71")
placeholder.grid(row=0, column=0)
rootHelloLabel.grid(row=1, column=0)

placeholder1 = tk.Label(root, text="", pady=70, bg="#ACAD71")
placeholder1.grid(row=2, column=0)
loginButton = tk.Button(root, pady=30, padx=80, text="Login", font=("Arial Bold", 27),
                        bg="#71AD90", fg="#D0CFD1", command=login)
loginButton.grid(row=3, column=0)

adminButton = tk.Button(root, pady = 10, padx = 40, text="Admin", 
                        font=("Arial Bold", 27), bg="#71AD90", fg="#D0CFD1")
adminButton.grid(row=5, column=0)

CodePudding user response:

I made three small changes and I think it works.

number = 0
number1 = str(number)

Labe = tk.Label(root, width=10,bd=1, bg="#ADA5A5", font=("Arial Bold", 36), fg="White")
Labe.grid(row=0, column=0)

def work():
   global number1
   Labe['text'] = "Loading"   " "   number1   "%"
   global number
   number = number   1
   number1 = str(number)
   if number == 102:
      root.after(1000)
      print("end")
      Labe.grid_remove()

num = 101
for x in range(num):
    print("He")
    root.after(50, work)
    root.after(50)
    root.update()  # added this so the window displays for one frame
# it's similar to mainloop() but only runs once

#Adding stuff to root
rootHelloLabel = tk.Label(root, text="Ordering system, please sign in", bg="#7271AD",
                          fg="White", font=("Arial Bold", 40), width=48, height=2)
placeholder = tk.Label(root, text="", pady=20, bg="#ACAD71")
placeholder.grid(row=0, column=0)
rootHelloLabel.grid(row=1, column=0)

placeholder1 = tk.Label(root, text="", pady=70, bg="#ACAD71")
placeholder1.grid(row=2, column=0)
loginButton = tk.Button(root, pady=30, padx=80, text="Login", font=("Arial Bold", 27),
                        bg="#71AD90", fg="#D0CFD1", command=lambda: login())
loginButton.grid(row=3, column=0)  # added lambda function so this only runs when clicked

adminButton = tk.Button(root, pady = 10, padx = 40, text="Admin", 
                        font=("Arial Bold", 27), bg="#71AD90", fg="#D0CFD1")
adminButton.grid(row=5, column=0)


root.mainloop()  # added this so that the program runs when done (can remove aswell)

I hope this works for you. I didnt quite understand the question but once I added the update() function it worked fine and I realised what you mean by a loading bar. I hope this helps!

CodePudding user response:

You runs 100 times after(50) in for-loop so it can stop program for 5 second. And I don't know if you really need it.

And I would run after(50, work) directly in work

def work():
    global number   # PEP8: all `global` at the beginning of function

    labe['text'] = f"Loading {number}%"
    number  = 1

    if number > 100:
        root.update() # to update last text in label because `after(1000)` will block it
        root.after(1000)
        print("end")
        labe.grid_remove()
    else:
        root.after(50, work)

Full working code (with other changes):

PEP 8 -- Style Guide for Python Code

import tkinter as tk

# --- functions ---   # PEP8: all functions directly after imports (and after all classes)

def work():
    global number   # PEP8: all `global` at the beginning of function

    labe['text'] = f"Loading {number}%"
    number  = 1

    if number > 100:
        root.update() # to update last text in label because `after(1000)` will block it
        root.after(1000)
        print("end")
        labe.grid_remove()
    else:
        # run again
        root.after(50, work)
    
def login():
    pass

# --- main ---

number = 0

root = tk.Tk()

labe = tk.Label(root, width=10, bd=1, bg="#ADA5A5", font=("Arial Bold", 36), fg="White")
labe.grid(row=0, column=0)

root_hello_label = tk.Label(root, text="Ordering system, please sign in", bg="#7271AD",
                            fg="White", font=("Arial Bold", 40), width=48, height=2)
root_hello_label.grid(row=1, column=0)

placeholder1 = tk.Label(root, text="", pady=20, bg="#ACAD71")
placeholder1.grid(row=0, column=0)

placeholder2 = tk.Label(root, text="", pady=70, bg="#ACAD71")
placeholder2.grid(row=2, column=0)

login_button = tk.Button(root, pady=30, padx=80, text="Login", font=("Arial Bold", 27),
                         bg="#71AD90", fg="#D0CFD1", command=login)
login_button.grid(row=3, column=0)

admin_button = tk.Button(root, pady = 10, padx = 40, text="Admin", 
                         font=("Arial Bold", 27), bg="#71AD90", fg="#D0CFD1")
admin_button.grid(row=5, column=0)

# run first time
root.after(50, work)

root.mainloop()

EDIT:

If you need to run with for-loop then you should rather set different times in after(..., work)

for i in range(1, 102):
    root.after(50*i, work)

Full working code:

import tkinter as tk

# --- functions ---   # PEP8: all functions directly after imports (and after all classes)

def work():
    global number   # PEP8: all `global` at the beginning of function

    labe['text'] = f"Loading {number}%"
    number  = 1

    if number > 100:
        root.update() # to update last text in label because `after(1000)` will block it
        root.after(1000)
        print("end")
        labe.grid_remove()
    
def login():
    pass

# --- main ---

number = 0

root = tk.Tk()

labe = tk.Label(root, width=10, bd=1, bg="#ADA5A5", font=("Arial Bold", 36), fg="White")
labe.grid(row=0, column=0)

root_hello_label = tk.Label(root, text="Ordering system, please sign in", bg="#7271AD",
                            fg="White", font=("Arial Bold", 40), width=48, height=2)
root_hello_label.grid(row=1, column=0)

placeholder1 = tk.Label(root, text="", pady=20, bg="#ACAD71")
placeholder1.grid(row=0, column=0)

placeholder2 = tk.Label(root, text="", pady=70, bg="#ACAD71")
placeholder2.grid(row=2, column=0)

login_button = tk.Button(root, pady=30, padx=80, text="Login", font=("Arial Bold", 27),
                         bg="#71AD90", fg="#D0CFD1", command=login)
login_button.grid(row=3, column=0)

admin_button = tk.Button(root, pady = 10, padx = 40, text="Admin", 
                         font=("Arial Bold", 27), bg="#71AD90", fg="#D0CFD1")
admin_button.grid(row=5, column=0)

# 102-1 = 101 loops, because it needs to display values 0...100 which gives 101 values
for i in range(1, 102):  
    root.after(50*i, work)

root.mainloop()

EDIT:

Because after(1000) freezes all GUI for 1 second so it it better to use after(1000, remove_label) to execute other function after 1 second and this doesn't freeze GUI.

def work():
    global number

    labe['text'] = f"Loading {number}%"
    number  = 1

    if number > 100:
        root.after(1000, remove_label)
    else:
        root.after(50, work)

def remove_label():
    print("end")
    labe.grid_remove()
  • Related