调用命令后,TKINTER窗口冻结

时间:2019-04-09 13:50:41

标签: python tkinter

我有一个小的tkinter程序,允许用户输入用户的名称日期并将其存储到文本文件中。

一切正常。但是当执行 after 命令时,一切都会冻结2000毫秒,正如我在下面的代码中提到的那样。 之后命令执行后,我无法单击任何窗口小部件。

我已经阅读了相同问题的解决方案,但没有一个得到解决。

即使调用了“之后”命令,我如何也可以顺利运行脚本?

代码

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

1 个答案:

答案 0 :(得分:1)

请参见aftereffbot文档的以下摘录:

  

after(delay_ms, callback=None, *args)

     

注册在给定时间后调用的警报回调。

     

此方法注册一个回调函数,该函数将在给定的毫秒数后被调用。 Tkinter只保证不早于该回调被调用;如果系统繁忙,则实际延迟可能会更长。

     

您也可以省略回调。如果这样做,则此方法仅等待给定的毫秒数,而不处理任何事件(与time.sleep(delay_ms*0.001)相同)。

     

delay_ms
  延迟(以毫秒为单位)。

     

回调
  回调。这可以是任何可调用对象。

致电时

root.after(2000, label.grid_forget())

您通过2000作为延迟,以毫秒为单位,这很好。您还传递label.grid_forget()作为回调。但是,label.grid_forget()不是应有的可调用对象,它是一个函数调用。因此,它将被执行,并且其返回值将作为回调传递。由于.grid_forget()的返回值为None,因此您实际上是在呼叫

root.after(2000, None)

在上面的信息中,您可以看到None是回调的默认值,并且当您省略回调时,它仅等待给定的毫秒数,而不提供任何事件。由于您将None作为回调传递,因此基本上就省略了回调,因此tkinter会冻结。

您可以通过传递函数对象(可调用)作为回调而不是调用函数来解决此问题:

root.after(2000, label.grid_forget)