Reputation: 97
I have a small tkinter program that allows user to enter name and date from the user and store it to a text file.
Everything works fine. But when after command gets executed then everything gets freezes for 2000 milli-seconds as I have mention in the code below. I am not able to click at any widget when after command is executing.
I have read solution of same problem but didn't solve by any of them.
How can I run my script smoothly even after "after" command is called?
CODE
from Tkinter import *
def submit():
# Gets executed when submit button is clicked
label = Label(label_frame, text='SUBMITTED')
label.grid(row=3, column=0)
with open('file.txt', 'a') as f:
get_name = name_entry.get()
get_date = date_entry.get()
f.write('{} {}'.format(get_name, get_date))
root.update()
root.after(2000, label.grid_forget())
# Everything gets paused / freezed when it executes after command
root = Tk()
root.geometry('350x200')
frame = Frame()
label_frame = Frame()
# Setting name label and its entry
name_label = Label(frame, text='NAME')
name_entry = Entry(frame, width=30)
name_label.grid(row=0, column=0)
name_entry.grid(row=0, column=1)
# Setting date label and its entry
date_label = Label(frame, text='DATE')
date_entry = Entry(frame, width=30)
date_label.grid(row=1, column=0)
date_entry.grid(row=1, column=1)
# Setting submit button
submit_button = Button(frame, text='ADD', width=15, command=submit)
submit_button.grid(row=2, column=0, columnspan=5)
# Placing frames to window
frame.place(x=50, y=20)
label_frame.place(x=130, y=100)
root.mainloop()
Upvotes: 0
Views: 482
Reputation: 10532
See the following excerpt from the effbot documentation on after
:
after(delay_ms, callback=None, *args)
Registers an alarm callback that is called after a given time.
This method registers a callback function that will be called after a given number of milliseconds. Tkinter only guarantees that the callback will not be called earlier than that; if the system is busy, the actual delay may be much longer.
You can also omit the callback. If you do, this method simply waits for the given number of milliseconds, without serving any events (same as
time.sleep(delay_ms*0.001)
).delay_ms
Delay, in milliseconds.callback
The callback. This can be any callable object.
When you call
root.after(2000, label.grid_forget())
you pass 2000
as the delay in milliseconds, which is good. You also pass label.grid_forget()
as the callback. However, label.grid_forget()
is not a callable object as it should be, it's a function call. Therefore, it will be executed, and its return value will be passed as the callback. Because the return value of .grid_forget()
is None
, you're actually calling
root.after(2000, None)
In the information above, you can see that None
is the default value for the callback, and that when you omit the callback it simply waits for the given number of milliseconds, without serving any events. Since you're passing None
as the callback, you're basically omitting the callback, so tkinter freezes.
You can fix this by passing the function object (which is callable) as the callback, instead of calling the function:
root.after(2000, label.grid_forget)
Upvotes: 1