Диалоги ввода

dialogi vvoda Приемы программирования графических интерфейсов

Нам осталось реализовать заключительную часть. Сценарии упаковывания и распаковывания прекрасно справляются со своей работой как инструменты командной строки. Однако обработчики, имена которых указаны в сценарии mytools.py из примера 10.6, должны делать нечто, ориентированное на использование графического интерфейса. Поскольку оригинальные сценарии packer и unpacker живут в мире текстовых потоков ввода-вывода и командных оболочек, нам необходимо обернуть их программным кодом, который будет принимать входные параметры из графического интерфейса. В частности, нам необходимы диалоги, запрашивающие обязательные аргументы командной строки.

В первую очередь рассмотрим модуль, представленный в примере 10.9, и клиентский сценарий в примере 10.10, который использует приемы создания модального диалога, рассматривавшиеся в главе 8, чтобы отобразить форму ввода параметров для сценария packer. Программный код в примере 10.9 был выделен в отдельный модуль, потому что он может найти более широкое применение. Фактически мы будем повторно использовать его в реализации диалога для сценария unpacker и еще раз — в приложении PyEdit, в главе 11.

Этот модуль демонстрирует еще один способ автоматизации конструирования графических интерфейсов — его использование для создания рядов формы ввода позволяет заменить 7 или более строк программного кода для каждого ряда (6 — если не использовать связанную переменную или кнопку вызова диалога выбора файла) ровно на 1 строку. В модуле form.py, в главе 12, мы увидим другой, еще более автоматизированный способ конструирования форм. Однако уже такой автоматизации вполне достаточно, чтобы сэкономить десятки строк программного кода при создании нетривиальных форм.

Пример 10.9. PP4E\Gui\ShellGui\formrows.py

создает фрейм-ряд с меткой и полем ввода и дополнительной кнопкой, вызывающей диалог выбора файла; эта реализация была выделена в отдельный модуль, потому что она может с успехом использоваться и в других программах; вызывающая программа (или обработчики событий, как в данном случае) должна сохранять ссылку на связанную переменную на все время использования ряда;

from tkinter import * # виджеты и константы

from tkinter.filedialog import askopenfilename # диалог выбора файла

def makeFormRow(parent, label, width=15, browse=True, extend=False):

var = StringVar()

row = Frame(parent)

lab = Label(row, text=label + ‘?’, relief=RIDGE, width=width)

ent = Entry(row, relief=SUNKEN, textvariable=var)

row.pack(fill=X) # используются фреймы-ряды

lab.pack(side=LEFT) # с метками фиксированной длины

ent.pack(side=LEFT, expand=YES, fill=X) # можно использовать

if browse: # grid(row, col)

btn = Button(row, text=’browse…’) btn.pack(side=RIGHT) if not extend:

btn.config(command=

lambda: var.set(askopenfilename() or var.get()) ) else:

btn.config(command=

lambda: var.set(var.get() + ‘ ‘ + askopenfilename()) ) return var

Далее, функция runPackDialog в примере 10.10 является фактическим обработчиком, который вызывается при выборе имени инструмента в главном окне ShellGui. Она использует модуль конструирования рядов формы из примера 10.9 и применяет приемы создания модальных диалогов, которые мы изучали ранее.

Пример 10.10. PP4E\Gui\ShellGui\packdlg.py

# выводит диалог ввода параметров для сценария packer и запускает его

from glob import glob # расширение шаблонов имен файлов

from tkinter import * # виджеты графического интерфейса

from packer import pack # использовать сценарий/модуль packer

from formrows import makeFormRow # использовать инструмент создания форм

def packDialog(): # новое окно верхнего уровня

win = Toplevel() # с 2 фреймамирядами + кнопка ok win.title(‘Enter Pack Parameters’)

var1 = makeFormRow(win, label=’Output file’)

var2 = makeFormRow(win, label=’Files to pack’, extend=True) Button(win, text=’OK’, command=win.destroy).pack() win.grab_set()

win.focus_set() # модальный: захватить мышь, фокус ввода,

win.wait_window() # ждать закрытия окна диалога;

# иначе возврат произойдет немедленно return var1.get(), var2.get() # извлечь значения связанных переменных

def runPackDialog():

output, patterns = packDialog() # вывести диалог и ждать щелчка на

if output != “” and patterns != “”: # кнопке ok или закрытия окна patterns = patterns.split() # выполнить действия не связанные с filenames = [] # графическим интерфейсом

for sublist in map(glob, patterns): # вып. расширение шаблона вручную filenames += sublist # командные оболочки Unix

print(‘Packer:’, output, filenames) # делают это автоматически pack(ofile=output, ifiles=filenames) # вывод также можно показать в # графическом интерфейсе

if __name__ == ‘__main__’: root = Tk() Button(root, text=’popup’, command=runPackDialog).pack(fill=X) Button(root, text=’bye’, command=root.quit).pack(fill=X) root.mainloop()

Если запустить сценарий из примера 10.10 и щелкнуть на кнопке popup, он создаст форму ввода, как показано на рис. 10.6, — это тот же диалог, который будет показан в ответ на выбор инструмента в главном окне сценария mytools.py. Пользователь может ввести имена входных и выходных файлов с клавиатуры или щелкнуть на кнопке browseчтобы открыть стандартный диалог выбора файла. Допускается вводить шаблоны имен файлов — вызов функции glob в этом сценарии выполнит подстановку шаблона и отфильтрует имена несуществующих файлов. Командные оболочки в Unix осуществляют такую подстановку шаблонов автоматически, если запускать сценарий packer.py из командной строки, в отличие от Windows.

Рис. 10.6. Форма ввода packdlg

После того как пользователь заполнит форму и щелкнет на кнопке OK, параметры будут переданы главной функции сценария packer, представленного выше, для выполнения операции слияния файлов.

Графический интерфейс диалога ввода параметров для сценария unpacking выглядит проще, потому что в нем присутствует только одно поле ввода — имя файла архива. Здесь мы снова используем модуль конструирования рядов формы ввода, разработанного для диалога к сценарию packer, потому что эти две задачи очень похожи. Сценарий в примере 10.11 (и его главная функция, вызываемая графическим интерфейсом выбора инструмента в сценарии mytools.py) создает форму ввода, изображенную на рис. 10.7.

Рис. 10.7. Форма ввода unpkdlg

 

Пример 10.11. PP4E\Gui\ShellGui\unpkdlg.py

# выводит диалог ввода параметров для сценария unpacker и запускает его

from tkinter import * # классы виджетов

from unpacker import unpack # использовать сценарий/модуль unpacker

from formrows import makeFormRow # инструмент создания полей формы

def unpackDialog():

win = Toplevel()

win.title(‘Enter Unpack Parameters’)

var = makeFormRow(win, label=’Input file’, width=11)

win.bind(‘<Key-Return>’, lambda event: win.destroy())

win.grab_set()

win.focus_set() # сделать себя модальным

win.wait_window() # ждать возврата из диалога

return var.get() # или закрытия его окна

def runUnpackDialog():

input = unpackDialog() # получить входные параметры из диалога

if input != ‘’: # выполнить действия, не связанные с

print(‘Unpacker:’, input) # графическим интерфейсом, передав имя unpack(ifile=input, prefix=’’) # файла из диалога

if __name__ == “__main__”:

Button(None, text=’popup’, command=runUnpackDialog).pack()

mainloop()

Кнопка browseна рис. 10.7 выводит диалог выбора файла так же, как форма packdlg. Вместо кнопки OK этот диалог связывает событие нажатия клавиши Enter с операцией закрытия окна и с завершением ожидания закрытия модального диалога; при этом имя файла архива передается экземпляру класса главной функции сценария unpacker, представленного выше, для выполнения фактической процедуры сканирования файла.

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Каталог сайтов Всего.ру
Оцените статью
Секреты программирования
Добавить комментарий