How to update a progress bar in a loop? - python

What is the easy method to update Tkinter progress bar in a loop?
I need a solution without much mess, so I can easily implement it in my script, since it's already pretty complicated for me.
Let's say the code is:
from Tkinter import *
import ttk
root = Tk()
root.geometry('{}x{}'.format(400, 100))
theLabel = Label(root, text="Sample text to show")
theLabel.pack()
status = Label(root, text="Status bar:", bd=1, relief=SUNKEN, anchor=W)
status.pack(side=BOTTOM, fill=X)
root.mainloop()
def loop_function():
k = 1
while k<30:
### some work to be done
k = k + 1
### here should be progress bar update on the end of the loop
### "Progress: current value of k =" + str(k)
# Begining of a program
loop_function()

Here's a quick example of continuously updating a ttk progressbar. You probably don't want to put sleep in a GUI. This is just to slow the updating down so you can see it change.
from Tkinter import *
import ttk
import time
MAX = 30
root = Tk()
root.geometry('{}x{}'.format(400, 100))
progress_var = DoubleVar() #here you have ints but when calc. %'s usually floats
theLabel = Label(root, text="Sample text to show")
theLabel.pack()
progressbar = ttk.Progressbar(root, variable=progress_var, maximum=MAX)
progressbar.pack(fill=X, expand=1)
def loop_function():
k = 0
while k <= MAX:
### some work to be done
progress_var.set(k)
k += 1
time.sleep(0.02)
root.update_idletasks()
root.after(100, loop_function)
loop_function()
root.mainloop()

Related

Tkinter progress bar not working properly

I am trying to add a progress bar to my window until some work is being done. But it is not working properly. I want it to keep moving until the work is done but it just moves rapidly and then stops. Also if I try to minimize or close the progress window it just hangs and stops responding.
Can anyone help me how can I do it properly? Here is my code.
import time
from tkinter import ttk
from tkinter import *
numbers = []
def main():
main_window = Tk()
app = info(main_window)
main_window.mainloop()
class info:
def __init__(self, root):
# start = timer()
self.error_str = ''
self.root1 = root
self.root1.title('LOADING......')
self.root1.geometry("380x200")
self.root1.eval('tk::PlaceWindow . center')
self.root1.resizable(width=False, height=False)
self.root1.configure(background='white')
progress = ttk.Progressbar(self.root1, orient=HORIZONTAL,
length=380, mode='determinate')
progress.place(x=0, y=100)
i = 20
for x in range(1, 50):
numbers.append(x * 2)
print(numbers)
progress['value'] = i
self.root1.update_idletasks()
time.sleep(0.1)
i = i + 40
self.root = root
self.root.title('Second window')
self.root.geometry('1350x800+0+0')
frame1 = Frame(self.root, bg='#7877a5')
frame1.place(x=0, y=0, width=1350, height=150)
title = Label(frame1, text="Second Window", font=("Times New Roman", 40, "bold", "italic"),
bg='#7877a5',
fg='white')
title.place(x=380, y=45)
if __name__ == '__main__':
main()
Generally speaking you shouldn't call time.sleep() in a tkinter application because it interferes with the GUI's mainloop() and will make your program hang or freeze. Use the universal widget method after() instead.
Lastly you need to specify a maximum value for the Progressbar so its indicator scales properly relatively to the values of i you are setting its value to. The default for maximum is only 100, which your code was greatly exceeding in the for x loop.
Here's the code that needs to change in info.__init__(). The two lines changed have # ALL CAPS comments:
progress = ttk.Progressbar(self.root1, orient=HORIZONTAL,
length=380, mode='determinate',
maximum=(48*40)+20) # ADDED ARGUMENT.
progress.place(x=0, y=100)
i = 20
for x in range(1, 50):
numbers.append(x * 2)
print(numbers)
progress['value'] = i
self.root1.update_idletasks()
self.root1.after(100) # Delay in millisecs. # REPLACED TIME.SLEEP() CALL.
i = i + 40

Tkinter label does not change images dynamically

I want to change the image of the one labels in time with 2 other images but it immideatly skipts to the last one. Any suggestions?
I have tried using time.sleep incase it might happen so fast that before i could notice but it didnt work.
import tkinter
from tkinter import *
from PIL import Image , ImageTk
import time
window = tkinter.Tk()
window.geometry("500x500")
window.title("Pomodoro Timer")
window.image_1 = ImageTk.PhotoImage(Image.open("1.jpg"))
window.image_2 = ImageTk.PhotoImage(Image.open("2.jpg"))
window.image_3 = ImageTk.PhotoImage(Image.open("3.jpg"))
lbl_1 = tkinter.Label(window, image=window.image_1)
lbl_1.place(x=150,y=100)
lbl_2 = tkinter.Label(window, image=window.image_2)
lbl_2.place(x=200,y=100)
def display_numbers():
lbl_1
lbl_2
display_numbers()
def clicked():
i=1
while i<3:
if i==1:
lbl_1.configure(image=window.image_2)
time.sleep(0.91)
i += 1
elif i==2:
lbl_1.configure(image=window.image_3)
time.sleep(0.91)
i += 1
btn = tkinter.Button(window, text="Start", command=clicked)
btn.place(x=200,y=450,width=100)
window.mainloop()

How to record the execution time of a function called by a button?

I am creating an application (or program) that after the button is clicked creates a new window and displays the results of some maths in a listbox. I want it to also display the execution time of the math. I tried using time.time(), but apparently, I can't use that in a function.
I also tried using timeit, but I have no clue how to use it.
How else can I do this?
from tkinter import *
root = Tk()
def do_math():
window = Toplevel(root)
listbox = Listbox(window)
for i in range(1, 10):
math = i ** 2
listbox.insert(END, str(math))
time = Label(window, text="The math took {} seconds to execute.")
time.pack()
listbox.pack()
b1 = Button(root, text="Click me!", command=do_math).pack()
root.mainloop()
You can't use time.time() function because you had a variable named time inside your function which was causing some exception popping out (UnboundLocalError), renaming that variable to something else OR inserting global time ontop of the function would fix it in your case.
from tkinter import *
from time import time
root = Tk()
def do_math():
# global time
window = Toplevel(root)
listbox = Listbox(window)
start = time()
for i in range(1, 10000):
math = i ** 2
listbox.insert(END, str(math))
total = time() - start
label = Label(window, text="The math took {} seconds to execute.".format(str(total)))
label.pack()
listbox.pack()
b1 = Button(root, text="Click me!", command=do_math).pack()
root.mainloop()

How to Refresh Tkinter Display on a Cycle with No Lag

I'm trying to create a simple program to monitor data that displays in a Tkinter window and refreshes itself every second. The method I'm currently using creates an ever-increasing lag in the refresh cycle as the program runs.
This is a super simplified representation of the approach in the form of a counter. While the cycle begins at the intended rate of one second per loop, even after just a few minutes the cycle-time becomes noticeably slower. Any suggestions to eliminate this lag accumulation would be greatly appreciated. Thanks so much!
from tkinter import *
i=0
root = Tk()
root.title("Simple Clock")
root.configure(background="black")
def Cycle():
global i
Label(root, text="------------------------", bg="black", fg="black").grid(row=0, column=0, sticky=W)
Label(root, text = i, bg="black", fg="gray").grid(row=0, column=0, sticky=W)
i += 1
root.after(1000,Cycle)
root.after(1000,Cycle)
root.mainloop()
Stop creating new objects with each call. Instead, only update the parts that change. For the code above it would be updating the 2nd Label's text:
from tkinter import *
def Cycle():
global i
labels[1]['text'] = i
i += 1
root.after(1000,Cycle)
i=0
root = Tk()
root.title("Simple Clock")
root.configure(background="black")
labels = list()
labels.append(Label(root, text="------------------------", bg="black", fg="black"))
labels.append(Label(root, bg="black", fg="gray"))
for j in range(len(labels)):
labels[j].grid(row=0, column=0, sticky=W)
root.after(1000,Cycle)
root.mainloop()

Trouble with progressbar in tkinter

This is my code
janela_barra=Toplevel()
janela_barra.title("Processando...")
janela_barra["bg"]="light grey"
janela_barra.minsize(width=400, height=80)
janela_barra.maxsize(width=400, height=80)
comprimento = janela_barra.winfo_screenwidth()
altura = janela_barra.winfo_screenheight()
x = (comprimento/2)-(400/2)
y = (altura/2)-(80/2)
janela_barra.geometry("400x80+%d+%d" % (x, y))
janela_barra.iconbitmap('icon6.ico')
pb = ttk.Progressbar(janela_barra, orient=HORIZONTAL, length=200, mode='determinate')
pb.grid(column=0,row=0)
pb["value"]=0
pb["maximum"]=100
and then there is this inside a for:
for i in range(0,tamanho):
pb["value"]=i
pb.update()
where tamanho is the number of iterations of a for(420 right now), but the thing is, it only opens a windows and then closes, i can't see the progressbar actually function, no matter how much i increase tamanho
Just add sleep (from module time) in your loop, you will see the progression. Here is an example:
from tkinter import Tk, Button, Toplevel
from tkinter import ttk
from time import sleep
root = Tk()
def fct_run_for():
top=Toplevel(root)
top.title("Progression")
pb = ttk.Progressbar(top, orient="horizontal", length=200, mode='determinate')
pb.grid(column=0,row=0)
pb["value"]=0
pb["maximum"]=100
for i in range(100):
pb["value"] += 1
pb.update()
sleep(0.1)
Button(root, text="Run", command=fct_run_for).pack()
root.mainloop()

Categories