Виджет Menu

Меню – это виджет, который присутствует во многих пользовательских приложениях. Находится оно под строкой заголовка и представляет собой выпадающие списки под словами-пунктами меню. Пункты конечных списков представляют собой команды, обычно выполняющие какое-либо действия или открывающие диалоговые окна.

В tkinter экземпляр меню создается от класса Menu, далее его надо привязать к виджету, на котором оно будет расположено. Обычно таковым выступает главное окно приложения. Его опции menu присваивается экземпляр Menu через имя связанной с экземпляром переменной.

from tkinter import *
 
root = Tk()
mainmenu = Menu(root) 
root.config(menu=mainmenu) 
 
root.mainloop() 

Если выполнить данный код, то никакого меню вы не увидите. Только тонкую полоску под заголовком окна, ведь ни одного пункта меню не было создано. Метод add_command() добавляет пункт меню:

… 
mainmenu.add_command(label='Файл')
mainmenu.add_command(label='Справка')

Панель главного меню

В данном случае "Файл" и "Справка" – это команды. К ним можно добавить опцию command, связав тем самым с какой-либо функцией-обработчиком клика. Хотя такой вариант меню имеет право на существование, в большинстве приложений панель меню содержит выпадающие списки команд, а сами пункты на панели командами по сути не являются. Клик по ним приводит лишь к раскрытию соответствующего списка.

В tkinter проблема решается созданием новых экземпляров Menu и подвязыванием их к главному меню с помощью метода add_cascade().

from tkinter import *
 
root = Tk()
 
mainmenu = Menu(root) 
root.config(menu=mainmenu) 
 
filemenu = Menu(mainmenu, tearoff=0)
filemenu.add_command(label="Открыть...")
filemenu.add_command(label="Новый")
filemenu.add_command(label="Сохранить...")
filemenu.add_command(label="Выход")
 
helpmenu = Menu(mainmenu, tearoff=0)
helpmenu.add_command(label="Помощь")
helpmenu.add_command(label="О программе")
 
mainmenu.add_cascade(label="Файл", menu=filemenu)
mainmenu.add_cascade(label="Справка", menu=helpmenu)
 
root.mainloop() 

Пункты меню

На основное меню (mainmenu), добавляются не команды, а другие меню. У filemenu и helpmenu в качестве родительского виджета указывается не root, а mainmenu. Команды добавляются только к дочерним меню. Значение 0 опции tearoff отключает возможность открепления подменю, иначе его можно было бы делать плавающим кликом мыши по специальной линии (в случае tearoff=0 она отсутствует).

Точно также можно подвязывать дочерние меню к filemenu и helpmenu, создавая многоуровневые списки пунктов меню.

… 
helpmenu = Menu(mainmenu, tearoff=0)
 
helpmenu2 = Menu(helpmenu, tearoff=0)
helpmenu2.add_command(label="Локальная справка")
helpmenu2.add_command(label="На сайте")
 
helpmenu.add_cascade(label="Помощь", menu=helpmenu2)
 
helpmenu.add_command(label="О программе")

Вложенное меню

Метод add_separator() добавляет линию разделитель в меню. Используется для визуального разделения групп команд.

В tkinter можно создать всплывающее меню, оно же контекстное (если настроить его появление по клику правой кнопкой мыши). Для этого экземпляр меню подвязывается не через опцию menu к родительскому виджету, а к меню применяется метод post(), аргументами которого являются координаты того места, где должно появляться меню.

from tkinter import *
 
def circle():
    c.create_oval(x, y, x+30, y+30)
 
def square():
    c.create_rectangle(x, y, x+30, y+30)
 
def triangle():
    c.create_polygon(x, y, x-15, y+30, x+15, y+30,
                    fill='white', outline='black')
 
root = Tk()
 
c = Canvas(width=300, height=300, bg='white')
c.pack()
 
menu = Menu(tearoff=0)
menu.add_command(label="Круг", command=circle)
menu.add_command(label="Квадрат", command=square)
menu.add_command(label="Треугольник", command=triangle)
 
x = 0
y = 0
def popup(event):
    global x, y
    x = event.x
    y = event.y
    menu.post(event.x_root, event.y_root)
 
c.bind("<Button-3>", popup)
 
root.mainloop()

Всплывающее меню

Здесь при клике на холсте правой кнопкой мыши в этой точке всплывает меню. При выборе пункта меню рисуется соответствующая фигура в этом же месте.

Практическая работа

Измените программу из практической работы предыдущего урока так, чтобы открытие и сохранение файлов выполнялось не через экземпляры Button, а через Menu. Команду очистки текстового поля поместите в контекстное меню.

Пример программы на Tkinter с меню

Курс с примерами решений практических работ: android-приложение, pdf-версия.

Создано

Обновлено