Во всех последних версиях Python (где используется библиотека Tk версии 8.0 и выше) можно связывать горизонтальную панель меню с объектом окна верхнего уровня (например, Tk или Toplevel). В Windows и Unix (X Window ) эта строка меню выводится вдоль верхнего края окна. В некоторых версиях Mac OS это меню при выборе окна заменяет то, что отображается в верхней части экрана. Иными словами, меню окон выглядят так, как принято на той платформе, на которой выполняется сценарий.
В основе этой схемы лежит построение деревьев, состоящих из объектов виджетов Menu. Нужно просто связать с окном один элемент Menu верхнего уровня, добавить другие объекты раскрывающихся меню в качестве каскадов для меню верхнего уровня и добавить элементы в каждый из раскрывающихся списков. Виджеты Menu перекрестно связываются со следующим, более высоким уровнем, с помощью аргумента родительского виджета и метода add_cascade виджета Menu. Делается это так:
1. Создать меню Menu верхнего уровня как дочерний элемент окна и записать ссылку на новый виджет Menu в атрибут menu.
2. Для каждого раскрывающегося меню создать новый объект Menu как дочерний для самого верхнего меню и добавить его как каскадный для самого верхнего меню с помощью метода add_cascade.
3. В каждое раскрывающееся меню, созданное на шаге 2, добавить элементы выбора вызовом метода add_comand, которому в аргументе command передать обработчик события выбора этого элемента.
4. Добавить каскадные подменю, создавая новые виджеты Menu как дочерние для того объекта Menu, который должен расширяться каскад- но, и связывая родительский и дочерний объекты с помощью метода add_cascade.
В конечном итоге получится дерево виджетов Menu с ассоциированными обработчиками событий. Однако все это, вероятно, проще показать в программном коде, чем на словах. В примере 9.1 создается главное меню с двумя раскрывающимися меню, File и Edit; в раскрывающемся меню Edit имеется собственное вложенное подменю.
Пример 9.1. PP4E\Gui\Tour\menu_win.py
# меню окна верхнего уровня в стиле Tk8.0
from tkinter import * # импортировать базовый набор виджетов
from tkinter.messagebox import * # импортировать стандартные диалоги
def notdone():
showerror(‘Not implemented’, ‘Not yet available’)
def makemenu(win):
top = Menu(win) # win = окно верхнего уровня
win.config(menu=top) # установить его параметр menu
file = Menu(top)
file.add_command(label=’New…’, command=notdone, underline=0) file.add_command(label=’Open…’, command=notdone, underline=0) file.add_command(label=’Quit’, command=win.quit, underline=0) top.add_cascade(label=’File’, menu=file, underline=0)
edit = Menu(top, tearoff=False)
edit.add_command(label=’Cut’, command=notdone, underline=0) edit.add_command(label=’Paste’, command=notdone, underline=0) edit.add_separator()
top.add_cascade(label=’Edit’, menu=edit, underline=0)
submenu = Menu(edit, tearoff=True)
submenu.add_command(label=’Spam’, command=win.quit, underline=0) submenu.add_command(label=’Eggs’, command=notdone, underline=0) edit.add_cascade(label=’Stuff’, menu=submenu, underline=0)
if __name__ == ‘__main__’:
root = Tk() # или Toplevel()
root.title(‘menu_win’) # информация для менеджера окон
makemenu(root) # создать строку меню
msg = Label(root, text=’Window menu basics’) # добавить что-нибудь ниже msg.pack(expand=YES, fill=BOTH)
msg.config(relief=SUNKEN, width=40, height=7, bg=’beige’) root.mainloop()
Значительная часть программного кода в этом примере выполняет установку обработчиков событий и тому подобного, поэтому полезно будет выделить фрагменты, участвующие в процессе построения дерева меню. Для меню File:
top = Menu(win) # прикрепить Menu к окну
win.config(menu=top) # связать окно и меню
file = Menu(top) # прикрепить Menu к Menu верх. ур.
top.add_cascade(label=’File’, menu=file) # связать родителя с потомком
Помимо построения дерева объектов меню этот сценарий демонстрирует некоторые часто встречающиеся параметры конфигурации меню: Линии-разделители
С помощью метода add_separator сценарий создает в меню Edit разделитель — это просто линия, используемая для разделения групп родственных пунктов.
Линии отрыва
Сценарий запрещает отрыв раскрывающегося меню Edit, передавая параметр tearoff=0 при создании виджета Menu. Линии отрыва — это пунктирные линии, по умолчанию появляющиеся в меню tkinter верхнего уровня. Щелчок на этой линии создает новое окно, содержащее меню. Они могут служить удобным средством упрощения навигации (можно сразу щелкнуть на пункте отрывного меню, не блуждая по дереву вложенных пунктов), но не на всех платформах принято их использовать.
Горячие клавиши
Сценарий использует параметр underline, чтобы назначить уникальную букву в пункте меню горячей клавишей. Параметр задает смещение буквы в строке метки пункта меню. Например, в Windows пункт Quit в меню File этого сценария можно выбрать, как обычно, с помощью мыши, а также нажатием клавиши Alt, затем f и затем q. Использовать параметр underline не обязательно — в Windows первая буква имени раскрывающегося меню автоматически становится горячей клавишей, а кроме того, для перемещения по меню и выбора раскрывающихся пунктов можно использовать клавиши со стрелками и Enter. Но явное определение горячих клавиш может облегчить использование больших меню. Например, последовательность клавиш Alt+E+S+S выполняет действие по завершению программы, предусмотренное пунктом Spam во вложенном подменю Stuff, без каких- либо перемещений с помощью мыши или клавиш со стрелками.
Посмотрим, во что все это превращается в переводе на пиксели. На рис. 9.1 изображено окно, появляющееся при запуске этого сценария в Windows 7 с моими настройками системы. Оно несколько иначе, но похоже отображается в Unix и Macintosh.
На рис. 9.2 изображено, что происходит при выборе раскрывающегося меню File. Обратите внимание, что виджеты Menu связываются, а не присоединяются с помощью менеджера компоновки — в действительности менеджер компоновки здесь вообще не участвует. Если запустить этот
Рис. 9.1. Сценарий menu_win: строка меню окна верхнего уровня
Рис. 9.2. Открытое меню File
сценарий, можно также заметить, что все элементы меню либо завершают выполнение программы, либо выводят стандартный диалог ошибки «Not Implemented» (Не реализовано). Этот пример просто демонстрирует работу с меню, но на практике обработчики событий выбора пунктов меню обычно выполняют более полезные вещи.
И наконец, на рис. 9.3 изображено, что происходит после щелчка по линии отрыва в меню File и выбора каскадного подменю в раскрывающемся меню Edit. Каскадные меню можно вкладывать друг в друга на любую глубину (но злоупотребление этой возможностью может запутать пользователей).
В библиотеке tkinter любое окно верхнего уровня может иметь собственное меню, в том числе и всплывающие окна, создаваемые виджетом Toplevel. Сценарий в примере 9.2 создает три всплывающих окна с такой же панелью меню, как в предыдущем примере. Если запустить его, он создаст картину, изображенную на рис. 9.4.
Рис. 9.3. Отрывное меню File и каскадное Edit
Рис. 9.4. Несколько окон верхнего уровня с меню
Пример 9.2. PP4E\Gui\Tour\menu_win-multi.py
from menu_win import makemenu # повторно использовать функцию создания меню from tkinter import *
root = Tk()
for i in range(3): # три всплывающих окна с меню
win = Toplevel(root)
makemenu(win)
Label(win, bg=’black’, height=5, width=25).pack(expand=YES, fill=BOTH) Button(root, text=”Bye”, command=root.quit).pack() root.mainloop()
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011