Menu - виджет меню
Меню – это виджет, который присутствует во многих пользовательских приложениях. Находится оно под строкой заголовка и представляет собой выпадающие списки под словами - пунктами меню. Пункты конечных списков представляют собой команды, обычно выполняющие какое-либо действия или открывающие диалоговые окна.
Меню может содержать много элементов, причем эти элементы сами могут представлять меню и содержать другие элементы. В зависимости от того, какой тип элементов мы хотим добавить в меню, будет отличаться метод, используемый для их добавления. В частности, нам доступны следующие методы:
- add_command(options): добавляет элемент меню через параметр
options
- add_cascade(options): добавляет элемент меню, который в свою очередь может представлять подменю
- add_separator(): добавляет линию-разграничитель
- add_radiobutton(options): добавляет в меню переключатель
- add_checkbutton(options): добавляет в меню флажок
Menu() - Главное меню
В tkinter экземпляр меню создается от класса Menu, далее его надо привязать к виджету, на котором оно будет расположено. Обычно таковым выступает главное окно приложения. Его опции menu присваивается экземпляр Menu через имя связанной с экземпляром переменной:
from tkinter import *
root = Tk()
mainmenu = Menu(root)
root.config(menu=mainmenu)
root.mainloop()
2
3
4
5
6
7
Если выполнить данный код, то никакого меню вы не увидите. Только тонкую полоску под заголовком окна, ведь ни одного пункта меню не было создано. Метод add_command()
добавляет пункт меню:
…
mainmenu.add_command(label='Файл')
mainmenu.add_command(label='Справка')
…
2
3
4
В данном случае «Файл» и «Справка» – это команды. К ним можно добавить опцию command, связав тем самым с какой-либо функцией-обработчиком клика. Хотя такой вариант меню имеет право на существование, в большинстве приложений панель меню содержит выпадающие списки команд, а сами пункты на панели командами по сути не являются. Клик по ним приводит лишь к раскрытию соответствующего списка.
Упражнения
Создайте визуально похожее меню программы блокнот или skype.
Реализуйте генерацию меню. Образец меню записан в виде массива:
menu_example = [ ['file', ['new', 'open', 'close']], ['edit', ['undo', 'cut', 'paste', 'delete']], ['format', ['word wrap', 'font']], ['view', ['zoom', 'status bar']], ['help', ['view help', 'about notepad']] ]
1
2
3
4
5
6
7
Подменю - Submenu
Подменю - это меню, подключенное к другому объекту меню.
В 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()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
На основное меню 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="О программе")
…
2
3
4
5
6
7
8
9
10
11
Метод add_separator()
добавляет линию разделитель в меню. Используется для визуального разделения групп команд.
Взаимодействие с меню
Отличительной особенностью элементов меню является способность реагировать на нажатия пользователя. Для этого у каждого элемента меню можно задать параметр command
, который устанавливает ссылку на функцию, выполняемую при нажатии:
from tkinter import *
from tkinter import messagebox
def edit_click():
messagebox.showinfo("GUI Python", "Нажата опция Edit")
root = Tk()
root.title("GUI на Python")
root.geometry("300x250")
main_menu = Menu()
main_menu.add_cascade(label="File")
main_menu.add_cascade(label="Edit", command=edit_click)
main_menu.add_cascade(label="View")
root.config(menu=main_menu)
root.mainloop()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Контекстное меню - Popup menu
В следующем примере мы создаем всплывающее меню. Всплывающее меню также называется контекстным меню. Это может быть показано в любом месте на клиентской области окна:
from tkinter import *
def showMenu(event):
print(event)
menu.post(event.x_root, event.y_root)
def onQuit():
quit()
root = Tk()
root.geometry("250x150+300+300")
root.title("Popup menu")
menu = Menu(root, tearoff=0)
menu.add_command(label="Exit", command=root.destroy)
menu.add_command(label="Quit", command=onQuit)
root.bind("<Button-3>", showMenu)
root.mainloop()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
В нашем примере мы создаем всплывающее меню с двумя командами:
- контекстное меню - это обычный виджет меню. Функция отрыва отключена. Теперь невозможно разделить меню на новое окно верхнего уровня:
menu = Menu(root, tearoff=0)
- Мы связываем событие
<Button-3>
с методомshowMenu()
. Событие генерируется, когда мы щелкаем правой кнопкой мыши на клиентской области окна:
root.bind("<Button-3>", showMenu)
- Метод
showMenu()
показывает контекстное меню. Всплывающее меню отображается в координатах x и y щелчка мыши:
def showMenu(event):
print(event)
menu.post(event.x_root, event.y_root)
2
3
Результат выполнения может:
В tkinter можно создать всплывающее меню и настроить его появление по клику правой кнопкой мыши. Для этого экземпляр меню подвязывается не через опцию menu к родительскому виджету, а к меню применяется метод post()
, аргументами которого являются координаты того места, где должно появляться меню:
from tkinter import *
x = 0
y = 0
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')
def popup(event):
global x, y
x = event.x
y = event.y
menu.post(event.x_root, event.y_root)
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)
c.bind("<Button-3>", popup)
root.mainloop()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Здесь при клике на холсте правой кнопкой мыши в этой точке всплывает меню. При выборе пункта меню рисуется соответствующая фигура в этом же месте.
Упражнения
- Напишите визуальное подобие простейшего текстового редактора, например программы Блокнот.
- Реализуйте главное меню
File
добавив кнопки:open
,save
иclose
. - Реализуйте работу кнопок (
open
,save
иclose
) используя диалоговые окна. - Добавьте текстовое поле с корректным отображением при масштабировании окна.
- Добавьте вызов контекстного меню с командами:
cut
,copy
иpaste
. - Реализуйте работу кнопок (
cut
,copy
иpaste
), обратившись к свойствам текстового поля. - Реализуйте функцию кнопки меню "переноса текста": при активации перенос текста происходит по словам.