Y0SHI0N
Y0SHI0N

Reputation: 23

Why is my progress bar does not show up in tkinter

I am trying to code a loading screen for my Tkinter 'app' and trying to make an animated progress bar. I followed the tutorial and adapted the code into my own version. At first, when I click run, the codes run nicely, but as soon as I added a function to animate the progress bar, the progress bare stopped showing up altogether. The code I ended up with is as follow:

from tkinter import *
import random
import time
import sqlite3
from tkinter import simpledialog
from tkinter import messagebox
from tkcalendar import *
from tkinter import ttk
import math
from PIL import Image, ImageTk
import winsound

#--------------Frames--------------------------
class VendingApp(Tk):
    def __init__(self):
        Tk.__init__(self)
        self._frame = None
        self.switch_frame(Loading)

    def switch_frame(self, frame_class):
        #Destroys current frame and replaces it with a new one.
        new_frame = frame_class(self)
        if self._frame is not None:
            self._frame.destroy()
        self._frame = new_frame
        self._frame.pack()

class Loading(Frame):    
    def __init__(self, master):
        Frame.__init__(self, master)


    def load():
        for x in range(100):
            Loading_bar['value'] += 1
            root.update_idiletasks()
            time.sleep(1)
##            

        Loading_bar = ttk.Progressbar(self, orient = HORIZONTAL,
                                      length = 500, mode = 'determinate')
        Loading_bar.pack(pady = 200)


        load()
        
#---------------------------------------------------------------------------------------




#----------------------------------------------------------------------------------------
if __name__ == "__main__":
    root = VendingApp()
    #Sets the size of the window
    root.geometry("1024x768")
    #Renames the TITLE of the window
    root.title("Vending machine")
    root.geometry("1024x768")
    root.resizable(False, False) 


    root.mainloop()

I created a separate file to try to see if it would work with just tkinter and no class with this code:

from tkinter import ttk
from tkinter import*
import time

root = Tk()

def load():
    for x in range(100):
        time.sleep(1)
        Loading_bar['value'] += 1
        root.update_idletasks()
   
    None


Loading_bar = ttk.Progressbar(root, orient = HORIZONTAL,
                            length = 500, mode = 'determinate')
Loading_bar.pack()

load()

root.mainloop()

And the result was that every time I launch it the program load indefinitely. Can someone please tell me what I did wrong, please? No need for correct code to be provided, just the error/s and some pointer on how to fix it is fine, Although correct code will be much much appreciated. Thank you!

Upvotes: 0

Views: 664

Answers (1)

figbeam
figbeam

Reputation: 7176

The sleep() function will suspend execution and also updates to the GUI.

Try using the after() function instead. It schedules the load() function for later but does not affect the rest of your program:

from tkinter import ttk
from tkinter import*
import time

root = Tk()

def load():
    current_value = Loading_bar.cget('value')
    if current_value < 100:
        root.after(10, load)
    Loading_bar.config(value=current_value+1)

Loading_bar = ttk.Progressbar(root, orient = HORIZONTAL,
                            length = 500, mode = 'determinate')
Loading_bar.pack()

load()

root.mainloop()

Adding new example

I have added a new example which is a modification of your original code. I create the progress bar in the __init__() function of the Loading() class. After the progress bar reaches 100 the progress bar is removed but not destroyed.

from tkinter import *
from tkinter import ttk

class VendingApp(Tk):
    def __init__(self):
        Tk.__init__(self)
        self._frame = None
        self.switch_frame(Loading)

    def switch_frame(self, frame_class):
        new_frame = frame_class(self)
        if self._frame is not None:
            self._frame.destroy()
        self._frame = new_frame
        self._frame.pack()

class Loading(Frame):    
    def __init__(self, master):
        Frame.__init__(self, master)
        self.Loading_bar = ttk.Progressbar(self, orient=HORIZONTAL,
                                           length=500, mode='determinate')
        self.Loading_bar.pack(pady=200)
        self.load()

    def load(self):
        current_value = self.Loading_bar.cget('value')
        if current_value < 100:
            self.after(10, self.load)
        else:
            self.Loading_bar.pack_forget()  # Removing widget from frame
        self.Loading_bar.config(value=current_value+1)

if __name__ == "__main__":
    root = VendingApp()
    root.geometry("1024x768")
    root.mainloop()

Does this work better?

Upvotes: 1

Related Questions