1

I'm trying to learn Tkinter module, but I can't undestand why the after method doesn't behave as expected. From what I know, it should wait ms milliseconds and then execute the function, but in my case the function gets executed many more time, not considering the time I write. Here's the code:

from tkinter import *

def doSomething():
    x = int(l["text"])
    l["text"] = str(x + 1)

root = Tk()
root.geometry("300x300")
l = Label(root, text="0")
l.pack()

while True:
    l.after(1000, doSomething)
    root.update()
    if int(l["text"]) >= 5:
        break

root.mainloop() 

After the first 2 seconds the label starts displaying humongous numbers

1
  • What is the purpose of while True, instead, you can move your if and root.after() inside the func. Commented Apr 3, 2021 at 10:15

2 Answers 2

2

After the first 2 seconds the label starts displaying humongous numbers

Keep in mind, while True, is an infinite loop, you are making infinite calls to root.after() means alot of events are being scheduled to be called after 1 second. Better way to do this is to remove your while and move it all inside your function.

from tkinter import *

root = Tk()

def doSomething():
    x = int(l["text"])
    l["text"] = x + 1
    if int(l["text"]) < 5: # Only repeat this function as long as this condition is met
        l.after(1000, doSomething)

root.geometry("300x300")
l = Label(root, text="0")
l.pack()

doSomething()

root.mainloop() 

Though the best way to write the function would be to create a variable and increase the value of that variable inside the function and then show it out:

from tkinter import *

root = Tk()

count = 0 # Initial value
def doSomething():
    global count # Also can avoid global by using parameters
    count += 1 # Increase it by 1 
    l['text'] = count # Change text
    if count < 5:
        l.after(1000, doSomething)

root.geometry("300x300")
l = Label(root, text=count)
l.pack()

doSomething() # If you want a delay to call the function initially, then root.after(1000,doSomething)

root.mainloop() 

This way you can reduce the complexity of your code too and make use of the variable effectively and avoid nasty type castings ;)

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks a lot! So I guess the best way to call after is inside a function, so that it can be executed as long as a certain condition is met, right? Because I don't understand why using the while True loop is a bad idea in this case. I get that i'm making infinite calls, but why isn't the method executing one call per second, as stated in the after(1000, doSomething)?
@FraSassone while does not wait 1 second for doSomething to get executed. As long as while is concerned, root.after() is just a line of code that does not stop it. One way to pause while in between is to use time.sleep() but it also has its disadvantages, always better to use after() and avoid while at all costs.
@FraSassone ~ Would appreciate marking this as the correct answer if this answered your questions correctly. Click here to learn how :D
Oh I'm sorry! I'm new here, thanks for the clarification <3
1

You are using infinite loop when using while True. Correct way is:

from tkinter import *

def doSomething():
    x = int(l["text"])
    l["text"] = str(x + 1)
    if x < 5:
        l.after(1000, doSomething)

root = Tk()
root.geometry("300x300")
l = Label(root, text="0")
l.pack()


doSomething()


root.mainloop() 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.