Окно TKINTER зависает при вызове команды after

У меня есть небольшая программа 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()

Почему вы думаете, что вам нужен метод after?

user10474264 09.04.2019 16:00

Возможный дубликат Как легко избежать зависания Tkinter?

ruohola 09.04.2019 16:01

Многозадачность — это ваше решение, так что вы не усыпите свой графический интерфейс. Интернет полон обучающих материалов и примеров модуля threading.

Javier 09.04.2019 16:04
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
314
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

См. следующий отрывок из документации эффбот на 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)

Спасибо большое. Ваше объяснение кристально ясное.

Santosh Karki 09.04.2019 17:57

Другие вопросы по теме