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.
Thanks
Tkinter provides a variety of built-in functions develop interactive and featured GUI (Graphical User Interface). after() function is also a Universal function which can be used directly on the root as well as with other widgets.
In order to create a tkinter application, we generally create an instance of tkinter frame, i.e., Tk(). It helps to display the root window and manages all the other components of the tkinter application. We can initialize the tkinter instance by assigning the variable to it.
window.mainloop() tells Python to run the Tkinter event loop. This method listens for events, such as button clicks or keypresses, and blocks any code that comes after it from running until you close the window where you called the method.
An Entry widget in Tkinter is nothing but an input widget that accepts single-line user input in a text field. To return the data entered in an Entry widget, we have to use the get() method. It returns the data of the entry widget which further can be printed on the console.
You need to give a function to be called after the time delay as the second argument to after
:
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 itself
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
Live-Demo: repl.it
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 frame.after(500, function=None)
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With