Label not updating in tkinter - python

I have asked a very similar question I believe 2 days ago and it got closed as a mod told me to look at other similar questions but none of the solutions worked. Does anyone have any idea how to fix the error. Here is the code at the moment all it does is print and display the first number in the sequence:
import tkinter as tk
#import time
window = tk.Tk()
window.title("Hello wold")
window.geometry("300x300")
timer = int(input("time in seconds "))
def update():
global timer
timer -= 1
print(timer)
hello = tk.Label(window, textvariable = timer)
hello.pack()
for i in range(timer):
window.after(1000, update)
tk.mainloop()

There are few issues in your code:
it is not recommended to use console input() in a GUI application
the for loop will be blocked by tk.mainloop() until the root window is closed. However the next iteration will raise exception since the root window is destroyed. Actually the for loop is not necessary.
Below is a modified example:
import tkinter as tk
window = tk.Tk()
window.title("Hello World")
window.geometry("300x300")
# it is not recommended to use console input() in a GUI app
#timer = int(input("time in seconds: "))
timer = 10 # use sample input value
def update(timer=timer):
hello['text'] = timer
if timer > 0:
# schedule to run update() again one second later
hello.after(1000, update, timer-1)
# create label once and update its text inside update()
hello = tk.Label(window)
hello.pack()
update() # start the after loop
# should run mainloop() only once
window.mainloop()

import tkinter as tk
#import time
window = tk.Tk()
window.title("Hello wold")
window.geometry("300x300")
timer = int(input("time in seconds "))
hello = tk.Label(window, text= timer)
hello.pack()
def update():
global timer
timer -= 1
print(timer)
hello.config(text=timer)
for i in range(timer):
window.after(1000, update)
tk.mainloop()
something like this should work

Try this:
import tkinter as tk
import time
window = tk.Tk()
window.title("Countdown Timer")
window.geometry("300x300")
timer = int(input("time in seconds "))
#var = tk.StringVar()
def update(cnt):
if cnt > 0:
window.after(1000, update, cnt-1)
print(cnt)
hello['text'] = cnt
hello = tk.Label(window, text=cnt)
#hello['text'] = timer
hello.pack()
update(timer)
tk.mainloop()

Related

why is the display not updating

i want to do a countdown but the changes are not showing until the final one. Example:
def countdown():
# setup of window and other labels etc
timer = calculated time # just placeholder
countdown_time = Message(countdownWindow, text=timer, font=("Courier",16,"bold"), width=100)
time.sleep(1)
while timer != "00:00:00":
timer = calculate time # this time will be a updated current time
root.after(1000, countdown_time.configure(text=timer)
root.after(1000, countdown)
the problem here is that it only opens the window once the final change has been complete, but I want it to update the label every time it is changed
according to your example:
from tkinter import Tk, Button, Label
import time
def countdown():
time_count = 0
time.sleep(1)
while time_count != 10:
time_count += 1
root.after(1000, lbl.configure(text=str(time_count)))
root.update()
root.after(1000, countdown) # invokes an endless loop
root = Tk()
btn = Button(root, text="countdown", command=countdown)
btn.pack()
lbl = Label(root, text="")
lbl.pack()
root.mainloop()

use a while true loop while the code below is still running (python)

Im making this game called:
IDLE PEN ,(MAKE PENS)
and every 1 second i get a bonus pen
how i get a bonus pen is doing this
Import time
While true
make a pen()
time.sleep(1)
but i have some code under the while true loop.
the code under the while true loop is like buttons to
upgrade the pens or make a pen
So how do i make the code under the while true loop work?
This is my game im happy for anyone to copy it
its not ready yet
import functools
import tkinter
import tkinter.messagebox
import time
from random import seed
from random import randint
# eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
window = tkinter.Tk()
window.title('Idle Pen')
def print_pen(number: int):
return f"Pens: {number}"
class pencount:
def __init__(self):
self.pencount = 0
self.text = tkinter.Text(height=1, width=30)
self.text.insert("1.0", print_pen(0))
self.text['state'] = 'disabled'
self.text.pack()
def changepencount(self, count):
if self.pencount + count < 0:
return
self.pencount = self.pencount + count
self.text['state'] = 'normal'
self.text.delete("1.0", "end")
self.text.insert("1.0", print_pen(self.pencount))
self.text['state'] = 'disabled'
self.text.pack()
pen = pencount()
changepenup = functools.partial(pen.changepencount, 1)
B = tkinter.Button(window, text="Make Pen", command=changepenup)
changependown = functools.partial(pen.changepencount, -100)
A = tkinter.Button(window, text='Penmaker', command=changependown)
Q = tkinter.Button(window, text="Quit", command=window.destroy)
U = tkinter.Button
# eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
B.pack()
A.pack()
Q.pack()
window.mainloop()
You could use threading to run your loop in separated thread and then main thread may run tkitner
OR you can use tkinter function after() (instead of while True) to run function with delay and this function should use again after() to run itself.
import tkinter as tk
# --- functions ---
def update():
global value
value += 1
text = f'make penny: {value}'
print(text)
label['text'] = text
# run again after 1s (1000ms)
root.after(1000, update)
# --- main ---
value = 0
root = tk.Tk()
label = tk.Label(root, text="make penny: 0")
label.pack()
button = tk.Button(root, text="Exit", command=root.destroy)
button.pack()
# run first time after 1s (1000ms)
root.after(1000, update)
root.mainloop()

Progress bar for loop does not appear until loop calculation is done

I'm having difficulty comprehending how progress bars work in the context of a loop. My example is as follows:
import time
from tkinter import ttk,Tk, Label, Button,Label,DoubleVar
MAX = 4
root = Tk()
root.title("My Progressbar")
root.geometry('500x500')
theLabel = Label(root, text="Progress")
theLabel.pack()
progress_var = DoubleVar()
progress_var.set(0)
progressbar = ttk.Progressbar(root, variable=progress_var,
length=400,maximum=MAX,mode='determinate')
progressbar.pack()
for i in range(MAX+1):
print(i) #Where I will eventually do all my work. Here I print i and pause .5 sec
time.sleep(.5)
progress_var.set(i)
root.update_idletasks()
# Add quit button
def _quit():
root.quit()
root.destroy()
quit_button = Button(master=root, text="Quit", bg='lightgray',command=_quit)
quit_button.pack()
root.mainloop()
I'm missing something obvious as the bar does not appear until after the loop is complete. Also, is it possible to indicate the % complete somewhere on the bar?
You do the "work" before the flow of execution even has a chance to reach root.mainloop. You'll want to simulate doing the work after starting the mainloop. Maybe you could add a button which, upon being clicked, simulates the work? Try this:
# ...
def do_work():
for i in range(MAX+1):
print(i) #Where I will eventually do all my work. Here I print i and pause .5 sec
time.sleep(.5)
progress_var.set(i)
root.update_idletasks()
# ...
do_work_button = Button(master=root, text="Do Work", command=do_work)
do_work_button.pack()
root.mainloop()
If you only just want to increase the value in the progressbar each 0.5 second.Try this:
import time
from tkinter import ttk,Tk, Label, Button,Label,DoubleVar
MAX = 4
root = Tk()
root.title("My Progressbar")
root.geometry('500x500')
theLabel = Label(root, text="Progress")
theLabel.pack()
progress_var = DoubleVar()
progress_var.set(0)
progressbar = ttk.Progressbar(root, variable=progress_var,
length=400,maximum=MAX,mode='determinate')
progressbar.pack()
def add():
if progress_var.get() < MAX:
print(progress_var.get())
progress_var.set(progress_var.get()+1)
root.after(500, add)
# Add quit button
def _quit():
root.quit()
root.destroy()
quit_button = Button(master=root, text="Quit", bg='lightgray',command=_quit)
quit_button.pack()
root.after(500, add)
root.mainloop()
If it is a specific work, you need to create thread or process.

Python/Tkinter - How can I create infinite copies of a window?

I want to make a window that is constantly created making many copies of its-self.
I have tried making an infinite loop that calls the function every time but that doesn't work. I also tried making one within the function but it just recreates the window after I close the old one. Does this mean that the window can't be duplicated?
import tkinter
import os
def win():
A = True
while A == True:
window = tkinter.Tk()
window.title('WHOOPS')
window.geometry('100x100')
window.configure(background= "green")
lbl = tkinter.Label(window, text= 'whoops', bg= 'red')
window.mainloop()
quit = False
while quit == False:
win()
Can someone show me how to duplicate a window without hard-coding a whole new block, for example, a new function for each of win2() and win3()?
The user should be able to see a practically infinite stream of windows that can only be stopped by using the KeyboardInterrupt or by closing the shell/interpreter.
If you create windows in a infinite loop you are never going to return control to the main_loop. You can follow one of the followings:
#1 You can initialize an integer to 0 and after a specific count update root and then again continue creating windows and after a specific count update root again and it goes on ...
import tkinter as tk
import time
def startInfiniteLoop():
i = 0
otherFrame = []
while True:
otherFrame.append(tk.Toplevel())
i += 1
if i%1000 == 0:
time.sleep(1)
root.update()
root = tk.Tk()
button_one = tk.Button(root, text="Infinite Window !", command=startInfiniteLoop)
button_one.grid(row=0, column=0)
root.mainloop()
#2 You can write a function that creates a window and from inside of that function call itself after specific time again and again.
import tkinter as tk
def startInfiniteLoop():
otherFrame = tk.Toplevel()
root.after(1000, startInfiniteLoop)
root = tk.Tk()
button_one = tk.Button(root, text="Infinite Window !", command=startInfiniteLoop)
button_one.grid(row=0, column=0)
root.mainloop()

How do I make a counter using Tkinter displaying how many times a button is pressed

I am trying to make a little piece of software to display how many times a button is pressed. I made the gui work, the button input works, but I can't figure out how to make the counter update each time I press the button, root.update() didn't work.
Code:
import RPi.GPIO as GPIO
import time
import os
import Tkinter as tk
from Tkinter import *
root = tk.Tk()
root.overrideredirect(True)
root.overrideredirect(False)
root.attributes('-fullscreen',True)
root.configure(background='black')
root.configure(cursor="none")
buttonPin = 21
GPIO.setmode(GPIO.BCM)
GPIO.setup(buttonPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
Counter = 69
w = Label(root, text=Counter, fg="white", bg="black", font=("Helvetica",80))
w.pack()
w.place(relx=0.5, rely=0.5, anchor=CENTER)
last_state = True
input_state = True
root.mainloop()
while True:
input_state = GPIO.input(buttonPin)
if (not input_state):
Counter += 1
print(Counter)
time.sleep(0.3)
Your while True loop won't be working as long as the GUI isn't closed. Try removing it and instead define a new function:
def ctr():
global input_state, buttonPin, Counter
input_state = GPIO.input(buttonPin)
if (not input_state):
Counter += 1
print(Counter)
root.after(30, ctr)
and call it once in the main body of script before root.mainloop():
ctr()

Categories

Resources