简体   繁体   中英

TKINTER window gets freezes when after command is called

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()

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM