Далее мы увидим, как создавать аналогичные структуры форм с помощью менеджера компоновки grid, где вместо фреймов размещение виджетов выполняется по номерам рядов и столбцов. Но сейчас, реализовав структуру формы, посмотрим, как применять технологию создания модальных диалогов к более сложным формам.
Сценарий в примере 8.19, используя функции makeform и fetch из предыдущего примера, создает форму и выводит ее содержимое подобно тому, как это делалось раньше. Но теперь поля ввода прикрепляются к новому всплывающему окну Toplevel, создаваемому по требованию и содержащему кнопку OK, генерирующую событие уничтожения окна. Как мы уже знаем, метод wait_window влечет приостановку программы, пока окно не будет закрыто.
Пример 8.19. PP4E\Gui\Tour\entry2-modal.py
# создает модальный диалог с формой;
# данные должны извлекаться до уничтожения окна с полями ввода
from tkinter import *
from entry2 import makeform, fetch, fields
def show(entries, popup): fetch(entries) # извлечь данные перед уничтожением окна!
popup.destroy() # если инструкции поменять местами, сценарий
# будет возбуждать исключение
def ask():
popup = Toplevel() # отобразить форму в виде модального диалога
ents = makeform(popup, fields)
Button(popup, text=’OK’, command=(lambda: show(ents, popup))).pack() popup.grab_set() popup.focus_set() popup.wait_window() # ждать закрытия окна
root = Tk()
Button(root, text=’Dialog’, command=ask).pack()
root.mainloop()
Если нажать кнопку в главном окне, сценарий создаст окно диалога с формой, блокирующее остальное приложение, изображенное на рис. 8.25.
В реализации этого модального диалога таится малозаметная опасность: поскольку он извлекает данные, вводимые пользователем, из виджетов Entry, встроенных во всплывающее окно, эти данные необходимо получить прежде чем окно будет уничтожено в обработчике события нажатия кнопки OK. Оказывается, что вызов destroy действительно уничтожает все виджеты окна — попытка получить значение из уничтоженного виджета Entry не только не действует, но и порождает исключение с выводом трассировочной информации и сообщения об ошибке в окне консоли — попробуйте изменить порядок команд в функции show, и вы убедитесь в этом сами.
Рис. 8.25. Окна, создаваемые сценарием entry2-modal (и entry3-modal)
Чтобы избежать этой проблемы, нужно следить за тем, чтобы выборка значений осуществлялась перед уничтожением, или использовать переменные tkinter, являющиеся предметом обсуждения следующего раздела.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011