Рассмотрим программу, представляющую лучшее применение тех двух классов автоматизации, которые мы написали. Класс Hello, реализованный в примере 10.4, является наследником обоих классов, GuiMixin и GuiMaker. Класс GuiMaker обеспечивает связь с виджетом Frame и логику создания меню/панели инструментов. Класс GuiMixin обеспечивает дополнительные методы стандартного поведения. В действительности класс Hello служит образцом еще одного способа расширения виджета Frame, поскольку является производным от класса GuiMaker. Чтобы бесплатно получить меню и панель инструментов, он просто следует протоколам, определенным в классе GuiMaker, — устанавливает атрибуты menuBar и toolBar в методе start и переопределяет метод makeWidgets, помещая в середину нестандартную метку.
Пример 10.4. PP4E\Gui\Tools\big_gui.py
реализация графического интерфейса — объединяет GuiMaker, GuiMixin и данный класс
import sys, os
from tkinter import * # классы виджетов
from PP4E.Gui.Tools.guimixin import * # подмешиваемые методы: quit, spawn…
from PP4E.Gui.Tools.guimaker import * # фрейм плюс построение меню/панели
# инструментов
class Hello(GuiMixin, GuiMakerWindowMenu): # или GuiMakerFrameMenu
def start(self):
self.hellos = 0
self.master.title(“GuiMaker Demo”)
self.master.iconname(“GuiMaker”)
def spawnme(): self.spawn(‘big_gui.py’) # отложен. вызов вместо lambda
self.menuBar = [ # дерево: 3 раскр. меню
(‘File’, 0, # (раскр. меню)
[(‘New…’, 0, spawnme),
(‘Open…’, 0, self.fileOpen), # [список элементов меню]
(‘Quit’, 0, self.quit)] # метка,клавиша,обработчик
),
(‘Edit’, 0,
[(‘Cut’, -1, self.notdone), # без клавиши| обработчика
(‘Paste’, -1, self.notdone), # lambda:0 тоже можно
‘separator’, # добавить разделитель
(‘Stuff’, -1,
[(‘Clone’, -1, self.clone),# каскадное подменю (‘More’, -1, self.more)] ), (‘Delete’, -1, lambda:0), [5]] # отключить ‘delete’
),
(‘Play’, 0,
[(‘Hello’, 0, self.greeting),
(‘Popup…’, 0, self.dialog),
(‘Demos’, 0,
[(‘Toplevels’, 0,
lambda: self.spawn(r’..\Tour\toplevel2.py’)),
(‘Frames’, 0,
lambda: self.spawn(r’..\Tour\demoAll-frm-ridge.py’)),
(‘Images’, 0,
lambda: self.spawn(r’..\Tour\buttonpics.py’)),
(‘Alarm’, 0,
lambda: self.spawn(r’..\Tour\alarm.py’, wait=False)), (‘Other…’, -1, self.pickDemo)]
)]
)]
self.toolBar = [ # добавить 3 кнопки
(‘Quit’, self.quit, dict(side=RIGHT)), # или {‘side’: RIGHT} (‘Hello’, self.greeting, dict(side=LEFT)), (‘Popup’, self.dialog, dict(side=LEFT, expand=YES)) ]
def makeWidgets(self): # переопределить метод
middle = Label(self, text=’Hello maker world!’, # создания виджетов
width=40, height=10, # в середине окна
relief=SUNKEN, cursor=’pencil’, bg=’white’)
middle.pack(expand=YES, fill=BOTH)
def greeting(self):
self.hellos += 1
if self.hellos % 3:
print(“hi”)
else:
self.infobox(“Three”, ‘HELLO!’) # каждый третий щелчок
def dialog(self):
button = self.question(‘OOPS!’,
‘You typed “rm*” … continue?’, # старый стиль ‘questhead’, (‘yes’, ‘no’)) # аргументы
[lambda: None, self.quit]() # игнорируются
def fileOpen(self):
pick = self.selectOpenFile(file=’big_gui.py’)
if pick: self.browser(pick) # просмотр файла модуля или другого файла
def more(self):
new = Toplevel()
Label(new, text=’A new non-modal window’).pack()
Button(new, text=’Quit’, command=self.quit).pack(side=LEFT) Button(new, text=’More’, command=self.more).pack(side=RIGHT)
def pickDemo(self):
pick = self.selectOpenFile(dir=’..’) if pick: self.spawn(pick) # запустить любую программу Python
if __name__ == ‘__main__’: Hello().mainloop() # создать, запустить
Этот сценарий создает довольно объемное меню и панель инструментов, а также добавляет собственные методы обратного вызова, которые выводят сообщения в поток stdout, отображают средства просмотра текстовых файлов и новые окна и запускают другие программы. Однако многие из этих методов не делают ничего, кроме запуска метода not— Done, унаследованного от класса GuiMixin. Данный пример предназначен в основном для демонстрации возможностей классов GuiMaker и GuiMixin. Если запустить big_gui как самостоятельный сценарий, он создаст окно с четырьмя раскрывающимися меню вверху и панелью инструментов с тремя кнопками внизу, как показано на рис. 10.3, где также изображены некоторые всплывающие окна, созданные обработчиками. В меню имеются разделители, неактивные элементы и каскадные подменю в полном соответствии с шаблоном menuBar, который передается классу GuiMaker, и кнопка Quit, унаследованная от класса GuiMixin, щелчок на которой вызывает появление диалога с просьбой подтвердить завершение работы. И это лишь часть инструментов, которые мы бесплатно получаем в свое распоряжение.
На рис. 10.4 снова изображено окно этого сценария после того как через раскрывающееся меню Play были запущены два демонстрационных сценария, которые мы написали в главах 8 и 9, выполняющиеся независимо. Эти демонстрационные сценарии были запущены с помощью переносимых инструментов, которые мы написали в главе 5 и приобрели из класса GuiMixin. Если у вас появится желание запустить какую-либо другую демонстрационную программу, выберите пункт Other в меню Play, который откроет стандартный диалог открытия файла, и выберите файл требуемой программы. Примечание: изображение ярлыка, используемое демонстрационным сценарием, запуск которого производится из меню Play, я скопировал в каталог с этим сценарием — позднее мы напишем инструменты, которые будут пытаться отыскивать его автоматически.
![]() |
|
![]() |
|
программ
Наконец, хочу заметить, что класс GuiMaker можно перепроектировать так, чтобы в нем использовались деревья вложенных экземпляров классов, умеющих применять себя к строящемуся дереву виджетов tkinter вместо ветвления по типам элементов в структурах данных шаблона. Однако ввиду недостатка места в данном издании мы отнесем это расширение к числу самостоятельных упражнений.
Коль скоро речь зашла о расширениях, — в главе 9 я демонстрировал, как вместо текстовых меток помещать на кнопки в панели инструментов изображения. Создание подкласса, наследующего класс GuiMaker, реализующего такую возможность за счет переопределения метода создания панели инструментов, стало бы не только отличным упражнением, но и позволило бы получить полезный инструмент. Однако если я буду добавлять реализацию каждой такой особенности, эта книга может разрастись настолько, что превратится в неподъемный груз…
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011