Solving problem is about exposing yourself to as many situations as possible like tkinter: how to use after method and practice these strategies over and over. With time, it becomes second nature and a natural way you approach any problems in general. Big or small, always start with a plan, use other strategies mentioned here till you are confident and ready to code the solution.
In this post, my aim is to share an overview the topic about tkinter: how to use after method, which can be followed any time. Take easy to follow this discuss.
Hey I am new to python and am using tkinter for my gui. I am having trouble using the “after” method.
The goal is to make a random letter appear every 5 seconds.
Here is my code:
import random import time from tkinter import * root = Tk() w = Label(root, text="GAME") w.pack() frame = Frame(root, width=300, height=300) frame.pack() L1 = Label(root, text="User Name") L1.pack(side=LEFT) E1 = Entry(root, bd =5) E1.pack(side=LEFT) tiles_letter = ['a', 'b', 'c', 'd', 'e'] while len(tiles_letter) > 0: rand = random.choice(tiles_letter) tile_frame = Label(frame, text=rand) tile_frame.pack() frame.after(500) tiles_letter.remove(rand) # remove that tile from list of tiles root.mainloop()
can someone please help me — the problem is definitely frame.after(500):
i’m not sure if it is correct to use “frame” and I don’t know what which argument follows the 500.
You need to give a function to be called after the time delay as the second argument to
after(delay_ms, callback=None, *args)
Registers an alarm callback that is called after a given time.
So what you really want to do is this:
tiles_letter = ['a', 'b', 'c', 'd', 'e'] def add_letter(): rand = random.choice(tiles_letter) tile_frame = Label(frame, text=rand) tile_frame.pack() root.after(500, add_letter) tiles_letter.remove(rand) # remove that tile from list of tiles root.after(0, add_letter) # add_letter will run as soon as the mainloop starts. root.mainloop()
You also need to schedule the function to be called again by repeating the call to
after inside the callback function, since
after only executes the given function once. This is also noted in the documentation:
The callback is only called once for each call to this method. To keep
calling the callback, you need to reregister the callback inside
Note that your example will throw an exception as soon as you’ve exhausted all the entries in
tiles_letter, so you need to change your logic to handle that case whichever way you want. The simplest thing would be to add a check at the beginning of
add_letter to make sure the list isn’t empty, and just
return if it is:
def add_letter(): if not tiles_letter: return rand = random.choice(tiles_letter) tile_frame = Label(frame, text=rand) tile_frame.pack() root.after(500, add_letter) tiles_letter.remove(rand) # remove that tile from list of tiles
I believe, the 500ms run in the background, while the rest of the code continues to execute and empties the list.
Then after 500ms nothing happens, as no function-call is implemented in the after-callup (same as