На этом шаге мы рассмотрим используемые для этих целей методы.
Жизненный цикл приложения включает в себя его инициализацию (в этот момент создаются все нужные компоненты и окна), запуск цикла обработки событий, собственно обработку событий (в процессе которой выполняются все полезные действия, ради которых и создается приложение) и завершение его работы. Для управления жизненным циклом предназначаются следующие методы, поддерживаемые всеми компонентами:
Полезность этого метода демонстрирует следующий пример. Это небольшое приложение имитирует выполнение длительного действия, вызывая в цикле функцию sleep() из модуля time. При этом на каждом проходе цикла в расположенную в окне надпись выводится порядковый номер текущего прохода цикла.
import tkinter import tkinter.ttk import time # Ради простоты поместим все элементы управления # непосредственно в окно class Application(tkinter.Tk): def __init__(self): super().__init__() self.create_widgets() self.title("update_idletasks") self.resizable(False, False) self.mainloop() def create_widgets(self): btnAction = tkinter.ttk.Button(self, text="Запустить действие", width=20, command=self.run) btnAction.pack() self.lblCounter = tkinter.ttk.Label(self, text="") self.lblCounter.pack() def run(self): for i in range(0, 51): time.sleep(0.1) self.lblCounter["text"] = str(i) # self.update_idletasks() app = Application()
Если мы нажмем кнопку Запустить действие, то увидим, что в надписи, где, по идее, должен выводиться номер текущего прохода цикла, ничего не появляется, и лишь по окончании выполнении действия в ней появится номер последнего, 50-го, прохода (рисунок 1).
Рис.1. Отображение только последнего номера
Это происходит потому, что приложение не имеет времени выполнить фоновые задачи - в частности, вывести на экран задаваемый для надписи текст (номер прохода цикла).
Теперь раскомментируем выражение, вызывающее метод update_idletasks():
# self.update_idletasks()
Сохраним код, запустим приложение и вновь нажмем кнопку Запустить действие. Мы сразу увидим, что в надписи выводятся последовательно увеличивающиеся номера проходов цикла - наше приложение работает нормально (рисунок 2).
Рис.2. Отображение всех номеров (показаны только некоторые из них)
Это происходит потому, что метод update_idietasks() принудительно выделяет приложению время на выполнение фоновых задач, - в частности, вывода на экран нового содержимого надписи (номера прохода цикла);
Метод возвращает целочисленный идентификатор созданной таким образом задержки. Его можно использовать впоследствии, чтобы отменить эту задержку до того, как она будет выполнена:
delay_id = self.after(1000, self.do_something, "abc", 10, False)
Здесь мы указываем выполнить метод do_something(), передав ему в качестве параметров значения "abc", 10 и False, спустя одну секунду (1000 миллисекунд).
Если второй параметр не указан, метод приостанавливает работу приложения на величину задержки. Фактически в этом случае он эквивалентен вызову функции sleep();
self.after_cancel(delay_id)
self.after_idle(self.rest, 7000)
Здесь мы указываем выполнить метод rest(), передав ему в качестве параметра число 7000, как только приложение станет простаивать;
Все эти три метода (wait_), будучи вызванными в обработчике события, не блокируют выполнение остальных обработчиков.
На следующем шаге мы рассмотрим взаимодействие с операционной системой.