У меня есть небольшая программа tkinter, которая позволяет пользователю вводить имя и Дата от пользователя и сохранять его в текстовом файле.
Все работает нормально. Но когда выполняется команда после, все зависает на 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()
Возможный дубликат Как легко избежать зависания Tkinter?
Многозадачность — это ваше решение, так что вы не усыпите свой графический интерфейс. Интернет полон обучающих материалов и примеров модуля threading
.
См. следующий отрывок из документации эффбот на 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.
Когда вы звоните
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)
Спасибо большое. Ваше объяснение кристально ясное.
Почему вы думаете, что вам нужен метод after?