18. Меню

Ссылка на урок, раздел Меню

Пример 1. Демонстрация меню

Код 18_6 в папке 18

import tkinter as tk
# creating tkinter window
root = Tk()
root.title('Демонстрация Меню')

# Создание панели меню
menubar = Menu(root)

# Добаввление Menu и commands
file = Menu(menubar, tearoff = 0)
menubar.add_cascade(label ='File', menu = file)
file.add_command(label ='New File', command = None)
file.add_command(label ='Open...', command = None)
file.add_command(label ='Save', command = None)
file.add_separator()
file.add_command(label ='Exit', command = root.destroy)

# Добавление и редактирование Menu и commands
edit = Menu(menubar, tearoff = 0)
menubar.add_cascade(label ='Edit', menu = edit)
edit.add_command(label ='Cut', command = None)
edit.add_command(label ='Copy', command = None)
edit.add_command(label ='Paste', command = None)
edit.add_command(label ='Select All', command = None)
edit.add_separator()
edit.add_command(label ='Find...', command = None)
edit.add_command(label ='Find again', command = None)

# Добавление Меню Help и commands
help_ = Menu(menubar, tearoff = 0)
menubar.add_cascade(label ='Help', menu = help_)
help_.add_command(label ='Tk Help', command = None)
help_.add_command(label ='Demo', command = None)
help_.add_separator()
help_.add_command(label ='About Tk', command = None)


root.config(menu = menubar)
mainloop()

Примечание: в приведенном выше приложении команды установлены на None, но можно добавлять различные команды к различным меткам для выполнения требуемой задачи.

help_.add_command(label =’Tk Help’, command = None)

Пример 2. Демонстрация меню

Код 18_7 в папке 18

import tkinter as tk

root = tk.Tk()
root.title("Tkinter Menubutton Tutorial")
root.geometry("250x150")

# Создайте виджет Menubutton
menubutton = tk.Menubutton(root, text="Menu Button")
menubutton.pack()

# Создайте виджет меню для кнопки Menubutton
menu = tk.Menu(menubutton, tearoff=False)

# Добавление опций в меню
menu.add_command(label="Option 1")
menu.add_command(label="Option 2")

# Свяжите меню с кнопкой Menubutton
menubutton.config(menu=menu)

root.mainloop()

Пример 3. Демонстрация меню

Код 18_8 в папке 18



import tkinter as tk
# Функция для обработки нажатий кнопок меню
def handle_click(menu_name, option_name):
    # Обновляйте текст надписи при нажатии на ту или иную опцию
    label.config(text=f"Clicked on {option_name} of {menu_name}")
    
# Создайте главное окно приложения
root = tk.Tk()
root.title("Tkinter Menubutton Example")
# Определите конфигурации для каждой кнопки меню
menus = [
    ("Menu 1", "above", 2, 10, False),
    ("Menu 2", "below", 3, 15, True),
    ("Menu 3", "left", 4, 20, True)
]
# Создайте ярлык для отображения выбранного параметра
label = tk.Label(root, text="")
label.pack(pady=5)

# Пройдитесь по списку конфигураций меню
for menu_name, direction, height, width, indicatoron in menus:
    # Создайте кнопку меню с указанными конфигурациями
    menubutton = tk.Menubutton(root, text=menu_name, direction=direction, height=height, width=width, indicatoron=indicatoron)
    menubutton.pack(pady=5)
    
    # Создайте меню для кнопки Menubutton
    menu = tk.Menu(menubutton)
    
    # Добавление команд в меню
    menu.add_command(label="Option 1", command=lambda: handle_click(menu_name, "Option 1"))
    menu.add_command(label="Option 2", command=lambda: handle_click(menu_name, "Option 2"))
    
    # Свяжите меню с кнопкой Menubutton
    menubutton.config(menu=menu)
    
root.mainloop()

Пример 4. Демонстрация меню

Код 18_9 в папке 18

import tkinter as tk

# Функция для обработки нажатий кнопок меню
def handle_click(menu_name, option_name):
label.config(text=f"Selected {option_name} from {menu_name}")
Создайте главное окно приложения
#
root = tk.Tk()
root.title("Candy Dispenser")

# Определите вкус конфет для каждого меню
candy_menu_options = {
"Jellybeans": ["Cherry", "Blueberry", "Lemon", "Watermelon"],
"Gummies": ["Strawberry", "Orange", "Apple", "Grape"],
"Hard Candy": ["Peppermint", "Butterscotch", "Cinnamon", "Sour Apple"]
}

# Функция для создания меню конфет
def create_candy_menu(menu_name, flavors):
menubutton = tk.Menubutton(root, text=menu_name, bg="pink", fg="white", font=("Arial", 12, "bold"), relief=tk.RAISED)
menubutton.pack(pady=5)

menu = tk.Menu(menubutton, tearoff=False)
for flavor in flavors:
menu.add_command(label=flavor, command=lambda f=flavor: handle_click(menu_name, f))

menubutton.config(menu=menu)

# Создавайте конфетные меню
for candy, flavors in candy_menu_options.items():
create_candy_menu(candy, flavors)

# Создайте этикетку для отображения выбранной конфеты
label = tk.Label(root, text="Select a candy flavor!", font=("Arial", 14))
label.pack(pady=10)

root.mainloop()

Пример 5. Демонстрация разных тем Меню

Код 18_10 в папке 18

import tkinter as tk
from tkinter import ttk

# Функция изменения цветовой гаммы
def change_theme(theme):
style.theme_use(theme)

# Создайте главное окно приложения
root = tk.Tk()
root.title("ttk Menubutton Example")

# Создайте стиль ttk
style = ttk.Style()

# Создайте тематическую кнопку меню
ttk_menubutton = ttk.Menubutton(root, text="Themes", width=10)
ttk_menubutton.pack(pady=20)

# Создайте меню для кнопки Menubutton
menu = tk.Menu(ttk_menubutton, tearoff=False)
ttk_menubutton.config(menu=menu)

# Добавьте цветовые темы в меню
themes = ["clam", "alt", "default", "vista", "xpnative", "winnative"]
for theme in themes:
menu.add_command(label=theme.capitalize(), command=lambda t=theme: change_theme(t))

# Примените исходную тему
change_theme(themes[0])

root.mainloop()

Пример 6. Демонстрация изменения цветов через Меню

Код 18_11 в папке 18

import tkinter as tk
from tkinter import ttk
def change_color(color):
root.configure(background=color)

# Создайте главное окно приложения
root = tk.Tk()
root.title("Color Theme Picker")

# Определите список цветовых опций
color_options = ["Red", "Green", "Blue", "Yellow"]

# Создайте кнопку меню ttk
theme_btn = ttk.Menubutton(root, text="Select Color Theme", width=20, compound="left", cursor="hand2")

# Создайте меню для кнопки Menubutton
theme_menu = tk.Menu(theme_btn, tearoff=False)

theme_btn.config(menu=theme_menu)

#
Заполните меню параметрами цвета
for color in color_options:
theme_menu.add_command(label=color, command=lambda c=color: change_color(c.lower()))

# Упакуйте кнопку меню
theme_btn.pack(padx=20, pady=20)

root.mainloop()

Пример 7. Демонстрация в стиле ttk Меню

Код 18_12 в папке 18

import tkinter as tk
from tkinter import ttk

# Создайте главное окно приложения
root = tk.Tk()
root.title("Stylish ttk Menubutton")

# Создайте объект в стиле ttk
style = ttk.Style()
style.theme_use("clam")
# Создайте пользовательский стиль для кнопки меню

style.configure("Custom.TMenubutton", background="yellow", foreground="orange", font=("georgia", 20, "bold"), borderwidth=2, relief="raised", width=15, arrowsize=20)
# Создайте кнопку меню ttk с пользовательским стилем

styled_btn = ttk.Menubutton(root, text="Style Me!", style="Custom.TMenubutton")
# Добавление опций в меню

menu = tk.Menu(styled_btn, tearoff=False)
menu.add_command(label="Option 1")
menu.add_command(label="Option 2")
styled_btn.config(menu=menu)

# Упакуйте кнопку меню
styled_btn.pack(padx=20, pady=20)

root.mainloop()

Пример 8. Демонстрация в стиле ttk Меню

Код 18_13 в папке 18

import tkinter as tk
from tkinter import ttk

# Функция для обработки щелчков по элементам меню
def handle_click(item):
label.config(text=f"Clicked on {item}")

# Создайте главное окно приложения
root = tk.Tk()
root.title("Stylish Toolbar with TTK Menubuttons")

#
Создайте объект в стиле ttk
style = ttk.Style()

# Настройте класс стиля Toolbutton
style.configure("Toolbutton", background="yellow", foreground="orange", font=("Verdana", 20, "bold"), borderwidth=2, relief="raised", padding=5)

# Создайте рамку панели инструментов
toolbar_frame = ttk.Frame(root)
toolbar_frame.pack(side=tk.TOP, fill=tk.X)

# Определение пунктов меню и их команд
menu_items = {
"File": [("Open", lambda: handle_click("Open")), ("Save", lambda: handle_click("Save")), ("Exit", root.quit)],
"Edit": [("Cut", lambda: handle_click("Cut")), ("Copy", lambda: handle_click("Copy")), ("Paste", lambda: handle_click("Paste"))],
"View": [("Zoom In", lambda: handle_click("Zoom In")), ("Zoom Out", lambda: handle_click("Zoom Out"))]
}

# Создайте кнопки меню ttk для панели инструментов
for text, items in menu_items.items():
btn = ttk.Menubutton(toolbar_frame, text=text, style="Toolbutton")
btn.pack(side=tk.LEFT)
menu = tk.Menu(btn, tearoff=False)
btn.config(menu=menu)
for label, command in items:
menu.add_command(label=label, command=command)

# Создайте метку для отображения выбранного элемента
label = tk.Label(root, text="")
label.pack(padx=10, pady=10)

root.mainloop()

Пример 9. Демонстрация в стиле ttk Меню

Код 18_14 в папке 18

import tkinter as tk
from tkinter import ttk

# Функция для обработки команд меню
def menu_command(action):
action_label.config(text=f"Selected action: {action}")

# Функция для обработки команд checkbutton
def check_command():
if check_var.get():
action_label.config(text="Checkbutton is checked")
else:
action_label.config(text="Checkbutton is unchecked")

# Функция для обработки команд radiobutton
def radio_command():
action_label.config(text=f"Selected option: {radio_var.get()}")

# Создайте главное окно приложения
root = tk.Tk()
root.title("Enhanced ttk Menubutton")

# Создайте кнопку меню ttk
menubutton = ttk.Menubutton(root, text="Menu", width=10)

# Создайте меню для кнопки Menubutton
menu = tk.Menu(menubutton, tearoff=False)
menubutton.config(menu=menu)

# Добавление опций в меню
menu.add_command(label="Open", command=lambda: menu_command("Open"))
menu.add_command(label="Save", command=lambda: menu_command("Save"))
menu.add_command(label="Close", command=lambda: menu_command("Close"))

# Добавьте подменю с дополнительными опциями
submenu = tk.Menu(menu, tearoff=False)
menu.add_cascade(label="Edit", menu=submenu)
submenu.add_command(label="Cut", command=lambda: menu_command("Cut"))
submenu.add_command(label="Copy", command=lambda: menu_command("Copy"))
submenu.add_command(label="Paste", command=lambda: menu_command("Paste"))

# Добавьте разделитель между параметрами
menu.add_separator()

# Добавьте больше опций
menu.add_command(label="Help", command=lambda: menu_command("Help"))
menu.add_command(label="About", command=lambda: menu_command("About"))

# Добавьте опцию checkbutton в меню
check_var = tk.BooleanVar()
menu.add_checkbutton(label="Check", variable=check_var, command=check_command)

# Добавьте подменю с параметрами радиокнопки
radio_var = tk.StringVar()
radio_submenu = tk.Menu(menu, tearoff=False)
menu.add_cascade(label="Options", menu=radio_submenu)
radio_submenu.add_radiobutton(label="Option 1", variable=radio_var, value="Option 1", command=radio_command)
radio_submenu.add_radiobutton(label="Option 2", variable=radio_var, value="Option 2", command=radio_command)
radio_submenu.add_radiobutton(label="Option 3", variable=radio_var, value="Option 3", command=radio_command)

# Создайте метку для отображения выбранного действия
action_label = tk.Label(root, text="Selected action: None")
action_label.pack(pady=10)

# Упакуйте кнопку меню
menubutton.pack(padx=20, pady=20)


root.mainloop()

Пример 10. Демонстрация текстового редактора

Создание настраиваемого интерфейса текстового редактора с помощью кнопок меню ttk

Давайте представим себе сценарий, в котором вы разрабатываете приложение текстового редактора.

В этом текстовом редакторе вы хотите включить панель инструментов с кнопкой ttk Menubutton для параметров форматирования, таких как стиль шрифта, размер и выравнивание.

Код 18_15 в папке 18

import tkinter as tk
from tkinter import ttk

# Функция для обработки щелчков по элементам меню
def handle_font_style(style):
text.config(font=(style, current_font_size.get()))

def handle_font_size(size):
text.config(font=(current_font_style.get(), size))

def handle_alignment(align):
text.tag_configure("align", justify=align)
text.tag_add("align", "1.0", "end")

# Создайте главное окно приложения
root = tk.Tk()
root.title("Text Editor")

# Создайте текстовый виджет
text = tk.Text(root, wrap="word")
text.pack(fill="both", expand=True)

# Создайте рамку панели инструментов
toolbar_frame = ttk.Frame(root)
toolbar_frame.pack(side=tk.TOP, fill=tk.X)

# Определение параметров стиля шрифта
font_styles = ["Arial", "Times New Roman", "Courier New"]

# Определите параметры размера шрифта
font_sizes = [10, 12, 14, 16, 18]

# Создайте кнопку меню ttk для стилей шрифтов
font_style_btn = ttk.Menubutton(toolbar_frame, text="Font Style", direction="above")
font_style_btn.pack(side=tk.LEFT, padx=5, pady=5)
font_style_menu = tk.Menu(font_style_btn, tearoff=False)
font_style_btn.config(menu=font_style_menu)
current_font_style = tk.StringVar()
for style in font_styles:
font_style_menu.add_radiobutton(label=style, variable=current_font_style, value=style, command=lambda s=style: handle_font_style(s))
current_font_style.set("Arial") # Стиль шрифта по умолчанию

# Создайте кнопку меню ttk для определения размеров шрифта
font_size_btn = ttk.Menubutton(toolbar_frame, text="Font Size", direction="above")
font_size_btn.pack(side=tk.LEFT, padx=5, pady=5)
font_size_menu = tk.Menu(font_size_btn, tearoff=False)
font_size_btn.config(menu=font_size_menu)
current_font_size = tk.IntVar()
for size in font_sizes:
font_size_menu.add_radiobutton(label=str(size), variable=current_font_size, value=size, command=lambda s=size: handle_font_size(s))
current_font_size.set(12) # Размер шрифта по умолчанию

# Создайте кнопку меню ttk для выравнивания текста
alignment_btn = ttk.Menubutton(toolbar_frame, text="Alignment", direction="above")
alignment_btn.pack(side=tk.LEFT, padx=5, pady=5)
alignment_menu = tk.Menu(alignment_btn, tearoff=False)
alignment_btn.config(menu=alignment_menu)
alignment_menu.add_command(label="Left", command=lambda: handle_alignment("left"))
alignment_menu.add_command(label="Center", command=lambda: handle_alignment("center"))
alignment_menu.add_command(label="Right", command=lambda: handle_alignment("right"))

root.mainloop()

Пример 11. Контекстное Меню – Popup menu

В следующем примере мы создаем всплывающее меню. Всплывающее меню также называется контекстным меню. Это может быть показано в любом месте на клиентской области окна:

Код 18_16 в папке 18

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()

В нашем примере мы создаем всплывающее меню с двумя командами:

контекстное меню – это обычный виджет меню.

Функция отрыва отключена. Теперь невозможно разделить меню на новое окно верхнего уровня:

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)

В tkinter можно создать всплывающее меню и настроить его появление по клику правой кнопкой мыши.

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

Код 18_17 в папке 18

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()

Здесь при клике на холсте правой кнопкой мыши в этой точке всплывает меню.

При выборе пункта меню рисуется соответствующая фигура в этом же месте.

Пример 12. Установка цвета в меню

Мы добавили опцию bg=’yellow’ установки цвета фона на желтый. Вот список опций, которые мы можем добавить.

Код 18_18 в папке 18

import tkinter  as tk 
my_w = tk.Tk()
my_w.geometry("350x120")

def my_fun():
pass
menubar = tk.Menu(my_w)

menu_file = tk.Menu(menubar, tearoff=0,bg='yellow') # file
menu_edit=tk.Menu(menubar,tearoff=0) # edit menu

menubar.add_cascade(label="File", menu=menu_file) # Top Line
menubar.add_cascade(label="Edit", menu=menu_edit) # Top Line

menu_file.add_command(label="New", command=my_fun()) # Item 1 of file
menu_file.add_command(label="Open..", command=my_fun()) # Item 2
#menu_file.add_command(label="Exit", command=lambda:exit()) # Item 3
#menu_file.add_command(label="Exit", command=my_w.destroy) # Item 3
menu_file.add_command(label="Exit", command=my_w.quit) # Item 3

menu_edit.add_command(label="Undo", command=my_fun())# Item 1 of Edit
menu_edit.add_command(label="Redo", command=my_fun())# Item 2 of Edit

my_w.config(menu=menubar) # adding menu to window
my_w.mainloop()

Пример 13. Цветные разделы Меню

Код 18_19 в папке 18

import tkinter  as tk 
my_w = tk.Tk()
my_w.geometry("250x120")

def my_fun():
pass

menubar = tk.Menu(my_w)
my_font1=('Times',12,'bold')
menu_file = tk.Menu(menubar,title='my title' ,
tearoff=1,fg='red',bg='yellow') # file
menu_edit=tk.Menu(menubar,tearoff=0) # edit menu
menu_sub=tk.Menu(menu_file,tearoff=0,bg='green')
menu_file.add_cascade(label='Sub 1',menu=menu_sub ) # add sub
menu_sub.add_command(label='Sub 11',command=my_fun())
menu_sub.add_command(label='Sub 12',command=my_fun())

menubar.add_cascade(label="File", menu=menu_file) # Top Line
menubar.add_cascade(label="Edit", menu=menu_edit) # Top Line

menu_file.add_command(label="New", command=my_fun()) # Item 1 of file
menu_file.add_command(label="Open..", command=my_fun()) # Item 2
menu_file.add_separator()

menu_file.add_command(label="Exit", command=my_w.quit) # Item 3
menu_edit.add_command(label="Undo", command=my_fun())# Item 1 of Edit
menu_edit.add_command(label="Redo", command=my_fun())# Item 2 of Edit

chkvar0=tk.BooleanVar(value=1) # checkbutton 1 selected
chkvar1=tk.BooleanVar()
menu_file.add_checkbutton(label='Chk 1',onvalue=1,offvalue=0,variable=chkvar0)
menu_file.add_checkbutton(label='Chk 2',onvalue=1,offvalue=0,variable=chkvar1)
optvar=tk.BooleanVar(value=1) # Radiobutton selected
menu_file.add_radiobutton(label='Option 1',value=1,variable=optvar)

my_w.config(menu=menubar) # adding menu to window
my_w.mainloop()

Здесь выбираем цвет. bg: фоновый цвет

menu_file = tk.Menu(menubar,title='my title' ,
tearoff=1,fg='red',bg='yellow') # file

Оторвать меню от основного окна. tearoff

Если значение параметра “отключение” равно 1 ( tearoff=1 ), то меню можно удалить из строки меню.

Нажмите на пунктирную линию вверху, чтобы отключить меню. Оно может принимать значения True или False (1 или 0).

menu_file = tk.Menu(menubar,title='my title',
tearoff=1,fg='red',bg='yellow') # file

Добавление кнопки radiobutton в меню. add_radiobutton()

Появляется галочка слева, от раздела меню. Если по умолчанию выключено, то chkvar0

menu_file.add_checkbutton(label='Chk 1',onvalue=1,offvalue=0,variable=chkvar0)
menu_file.add_checkbutton(label='Chk 2',onvalue=1,offvalue=0,variable=chkvar1)

Здесь мы добавим еще под меню

menu_sub2=tk.Menu(menu_sub,tearoff=0,bg='red')
menu_sub.add_cascade(label='Sub 2',menu=menu_sub2)
menu_sub2.add_command(label='Sub 21',command=my_fun())
menu_sub2.add_command(label='Child ',command=lambda:my_child())

Код 18_20 в папке 18

import tkinter  as tk 
my_w = tk.Tk()
my_w.geometry("250x120")

def my_fun():
pass

menubar = tk.Menu(my_w)
my_font1=('Times',12,'bold')
menu_file = tk.Menu(menubar,title='my title' ,
tearoff=1,fg='red',bg='yellow') # file

menu_edit=tk.Menu(menubar,tearoff=0) # edit menu
menu_sub=tk.Menu(menu_file,tearoff=0,bg='green')
menu_file.add_cascade(label='Sub 1',menu=menu_sub ) # add sub
menu_sub.add_command(label='Sub 11',command=my_fun())
menu_sub.add_command(label='Sub 12',command=my_fun())

# новое подменю
menu_sub2=tk.Menu(menu_sub,tearoff=0,bg='red')
menu_sub.add_cascade(label='Sub 2',menu=menu_sub2)
menu_sub2.add_command(label='Sub 21',command=my_fun())
menu_sub2.add_command(label='Child ',command=lambda:my_child())


menubar.add_cascade(label="File", menu=menu_file) # Top Line
menubar.add_cascade(label="Edit", menu=menu_edit) # Top Line

menu_file.add_command(label="New", command=my_fun()) # Item 1 of file
menu_file.add_command(label="Open..", command=my_fun()) # Item 2
menu_file.add_separator()

menu_file.add_command(label="Exit", command=my_w.quit) # Item 3
menu_edit.add_command(label="Undo", command=my_fun())# Item 1 of Edit
menu_edit.add_command(label="Redo", command=my_fun())# Item 2 of Edit

my_w.config(menu=menubar) # adding menu to window
my_w.mainloop()

Пример 14. Откройте новое окно по щелчку мыши в меню

Мы можем открыть дочернее окно по щелчку на пункте меню. Для работы на верхнем уровне нам нужно добавить эту строку вверху.

Код 18_21 в папке 18

import tkinter  as tk 
from tkinter import *

my_w = tk.Tk()
my_w.geometry("250x120")

def my_child():
my_w_child=Toplevel(my_w) # Child window
my_w_child.geometry("200x200") # Size of the window
my_w_child.title("www.plus2net.com")
my_str1 = tk.StringVar()
l1 = tk.Label(my_w_child, textvariable=my_str1 )
l1.grid(row=1,column=2)
my_str1.set("Привет я новое окно")
menubar = tk.Menu(my_w)
menu_file = tk.Menu(menubar,tearoff=0) # file
menu_edit=tk.Menu(menubar,tearoff=0) # edit menu
menubar.add_cascade(label="File", menu=menu_file) # Top Line
menubar.add_cascade(label="Edit", menu=menu_edit) # Top Line
menu_file.add_command(label="Новое окно", command=lambda:my_child())
menu_file.add_command(label="Exit", command=my_w.quit)
my_w.config(menu=menubar) # adding menu to window
my_w.mainloop()

С двухуровневым подменю и дочерним окном

postcommand

Здесь мы использовали postcommand для запуска функции Change_color(цвет), которая запускается раз в 1 секунду из-за рекурсивного вызова с использованием after().

Функция fg=color будет менять цвет шрифта на красный и зеленый каждые 1 секунду.

def Change_colour(color):
if color=='green':
color='red'
else:
color='green'
menu_file.config(fg=color)
my_w.after(1000,Change_colour, color)
menubar = tk.Menu(my_w)
my_font1=('Times',18,'bold')
menu_file = tk.Menu(menubar, fg='red',tearoff=0,bg='yellow',
font=my_font1, postcommand=lambda: Change_colour('green'))

Код 18_22 в папке 18

import tkinter  as tk 
from tkinter import *
my_w = tk.Tk()
my_w.geometry("250x120")

def my_fun():
pass

def my_child(): # to open child window
my_w_child=Toplevel(my_w) # Child window
my_w_child.geometry("200x200") # Size of the window
my_w_child.title("www.plus2net.com")
my_str1 = tk.StringVar()
l1 = tk.Label(my_w_child, textvariable=my_str1 )
l1.grid(row=1,column=2)
my_str1.set("Hi I am Child window")

# Меняем цвет раз в 1 сек.
def Change_colour(color):
if color=='green':
color='red'
else:
color='green'
menu_file.config(fg=color)
my_w.after(1000,Change_colour, color)
menubar = tk.Menu(my_w)
my_font1=('Times',18,'bold')
menu_file = tk.Menu(menubar, fg='red',tearoff=0,bg='yellow',selectcolor='green',
font=my_font1, postcommand=lambda: Change_colour('green'))


menu_edit=tk.Menu(menubar,tearoff=0) # edit menu
menu_sub=tk.Menu(menu_file,tearoff=0,bg='green')
menu_file.add_cascade(label='Sub 1',menu=menu_sub ) # add sub
menu_sub.add_command(label='Sub 11',command=my_fun())
menu_sub.add_command(label='Sub 12',command=my_fun())

menubar.add_cascade(label="File", menu=menu_file) # Top Line
menubar.add_cascade(label="Edit", menu=menu_edit) # Top Line

menu_file.add_command(label="New", command=my_fun()) # Item 1 of file
menu_file.add_command(label="Open..", command=my_fun()) # Item 2
menu_file.add_separator()

menu_file.add_command(label="Exit", command=my_w.quit) # Item 3
menu_edit.add_command(label="Undo", command=my_fun())# Item 1 of Edit
menu_edit.add_command(label="Redo", command=my_fun())# Item 2 of Edit

chkvar0=tk.BooleanVar(value=1) # checkbutton 1 selected
chkvar1=tk.BooleanVar()
menu_file.add_checkbutton(label='Chk 1',onvalue=1,offvalue=0,variable=chkvar0)
menu_file.add_checkbutton(label='Chk 2',onvalue=1,offvalue=0,variable=chkvar1)
optvar=tk.BooleanVar(value=1) # Radiobutton selected
menu_file.add_radiobutton(label='Option 1',value=1,variable=optvar)

menu_sub2=tk.Menu(menu_sub,tearoff=0,bg='red')
menu_sub.add_cascade(label='Sub 2',menu=menu_sub2)
menu_sub2.add_command(label='Sub 21',command=my_fun())
menu_sub2.add_command(label='Child ',command=lambda:my_child()) # Open child window

my_w.config(menu=menubar) # adding menu to window

print(menu_file.type(5)) # radiobutton
print(menu_file.type(7)) # separator
print(menu_file.type(9)) # checkbutton


my_w.mainloop()

Пример 15. Графический редактор Tkinter для управления текстовыми файлами

Создание меню

Мы будем использовать одно файловое меню с пунктами (опциями) для управления файловыми операциями.

Вот пункты, которые мы включим в наше файловое меню.

Файл

Новый: Чтобы создать файл с именем по умолчанию untitle.txt

Открыть:    Отображение диалогового окна файла с помощью функции askopefilename, предлагающей пользователю выбрать файл.

Сохранить: Сохраните данные, введенные в виджете «Текст» , в файл, отобразите диалоговое окно «Сохранить как файл», если имя файла untitle.txt .

Сохранить как:    Диалоговое окно «Файл» для сохранения файла под другим именем.

Закрыть: Сохраните файл (см. выше «Операция сохранения») и удалите содержимое из виджета «Текст».

Выход :      Закройте и выйдите из редактора. (С операцией сохранения файла)

Макет с компонентами GUI

у нас есть один виджет Menu , One Text в нашем окне.

Здесь мы установили переменную init_dir в папку, с которой хотим работать.

init_dir=’:\\testing\\file-menu\\’ # папка для работы

 Измените этот путь в зависимости от вашей системы.

Мы также объявили одну глобальную переменную file_name, так как будем использовать эту переменную внутри разных функций.

global file_name

Параметр command выполняет разные функции в зависимости от требуемой файловой операции. Эти функции описаны ниже.

import tkinter  as tk 
from tkinter import filedialog,END
from tkinter.filedialog import asksaveasfilename
my_w = tk.Tk()
my_w.geometry("409x350")
init_dir='D:\\testing\\file-menu\\' # folder to work
global file_name # global variable to store file name.

def my_fun():
pass

menubar = tk.Menu(my_w)
my_font1=('Times',12,'bold')
menu_f = tk.Menu(menubar,title='my title',tearoff=0) # file

menubar.add_cascade(label="File", menu=menu_f) # Top Line

menu_f.add_command(label="New",command=lambda:new_file())
menu_f.add_command(label="Open..",command=lambda:open_file())
menu_f.add_command(label="Save",command=lambda:save_file())
menu_f.add_command(label="Save As..",command=lambda:save_as_file())
menu_f.add_command(label="Close",command=lambda:close_file())
menu_f.add_command(label="Exit",command=my_w.quit)

my_w.config(menu=menubar) # adding menu to window

t1 = tk.Text(my_w, height=15, width=45) # added one text box
t1.grid(row=1,column=1,padx=30,pady=20)
my_w.mainloop()

new_file(): Создание нового файла

Внутри этой функции значение file_name устанавливается на untitle.txt . Заголовок окна устанавливается на file_name.

new_file(): Создание нового файла

def new_file():
global file_name
file_name='untitle.txt' # new file name
my_w.title(file_name) # Title of the window shows file name

open_file() : Открыть файл

def open_file():
file = filedialog.askopenfilename(filetypes=[("txt file",".txt")],
defaultextension=".txt",initialdir=init_dir)
global file_name
file_name=file # set the file name
my_w.title(file_name) # update the GUI title
fob=open(file,'r') # open in read mode
my_str1=fob.read() # read data from file & store in variable
t1.delete('1.0',END) # remove the previous content in text box
t1.insert(tk.END, my_str1) # add new data from file to text box
fob.close()

save_file() : Сохранить данные в файле

Если пользователь продолжил с именем файла по умолчанию untitle.txt , то будет вызвана функция save_as_file()

, чтобы отобразить диалоговое окно файла для ввода нового имени файла и сохранения файла.

Если имя файла уже доступно ( else part ), то файл открывается в режиме записи, и данные, собранные из виджета Текст, записываются в файл.

def save_file():
global file_name # collect the file name
if(file_name=='untitle.txt'): #if default file name is still there
save_as_file() # call the function
else:
fob=open(file_name,'w') # open in write mode
my_str1=t1.get("1.0",END) # collect the data from text widget
fob.write(my_str1) # write to file

save_as_file() : Сохранение файла под другим именем

Этот пункт меню используется, когда пользователь хочет сохранить файл под другим именем.

Таким образом, пользователю будет показано диалоговое окно сохранения файлаCancel .

Пользователь может нажать кнопку, поэтому мы проверим статус, используя проверку if else, и откроем файл в режиме записи для сохранения данных.

def save_as_file():
file = filedialog.asksaveasfilename(
filetypes=[("txt file", ".txt")],
defaultextension=".txt",initialdir=init_dir)
if file: # if user has not cancelled the dialog to save
fob=open(file,'w') # open the file in write mode
my_str1=t1.get("1.0",END) # collect data from text widget
fob.write(my_str1) # write to file
my_w.title(file) # Update the GUI title with file name
fob.close() # Close file pointer
else: # user has cancelled the operation
print("No file chosen")

close_file() Закрыть файл

Сначала мы вызовем функцию save_file() для выполнения операции сохранения файла.

Этот процесс можно удалить, если файл не нужно сохранять при закрытии, чтобы последние сохраненные данные остались.

Данные внутри виджета Текст удаляются, а Заголовок окна сохраняется как пустая строка.

def close_file():
save_file() # remove this line if not required
t1.delete('1.0',END) # remove the content from text widget
my_w.title('') # remove the title of GUI

Полный код

Код 18_23 в папке 18

import tkinter  as tk 
from tkinter import filedialog,END
from tkinter.filedialog import asksaveasfilename
my_w = tk.Tk()
my_w.geometry("409x350") # change width height
init_dir=':\\testing\\file-menu\\' # папка для работы
global file_name #
def new_file():
global file_name
file_name='untitle.txt' # новое имя файла
my_w.title(file_name)
def open_file():
file = filedialog.askopenfilename(filetypes=[("txt file", ".txt")],
defaultextension=".txt",initialdir=init_dir)
global file_name
file_name=file # задайте имя файла
my_w.title(file_name) # обновите заголовок графического интерфейса пользователя
fob=open(file,'r') # открыть в разделе читать далее
my_str1=fob.read() # считывание данных из файла
t1.delete('1.0',END) # удалите предыдущее содержимое
t1.insert(tk.END, my_str1) # добавление новых данных из файла в текстовое поле
fob.close()
def save_file():
global file_name # соберите имя файла
if(file_name=='untitle.txt'): # если имя файла по умолчанию все еще существует
save_as_file() # вызов функции
else:
fob=open(file_name,'w') # open in write mode
my_str1=t1.get("1.0",END) # collect the data from text widget
fob.write(my_str1) # write to file
def save_as_file():
file = filedialog.asksaveasfilename(
filetypes=[("txt file", ".txt")],
defaultextension=".txt",initialdir=init_dir)
if file: # если пользователь не отменил диалоговое окно для сохранения
fob=open(file,'w') # откройте файл в режиме записи
my_str1=t1.get("1.0",END) # сбор данных из текстового виджета
fob.write(my_str1) # запись в файл
my_w.title(file) # Обновите заголовок графического интерфейса пользователя на имя файла
fob.close() # Закрыть указатель на файл
else: # пользователь отменил операцию
print("No file chosen")
def close_file():
save_file() # удалите эту строку, если она не требуется
t1.delete('1.0',END) # удалить содержимое из текстового виджета
my_w.title('') # удалите заголовок графического интерфейса пользователя



menubar = tk.Menu(my_w)
my_font1=('Times',12,'bold')
menu_f = tk.Menu(menubar,title='my title',tearoff=0) # file

menubar.add_cascade(label="Файл", menu=menu_f) # Top Line

menu_f.add_command(label="Новый", command=lambda:new_file())
menu_f.add_command(label="Открыть..", command=lambda:open_file())
menu_f.add_command(label="Сохранить", command=lambda:save_file())
menu_f.add_command(label="Сохранить как..", command=lambda:save_as_file())
menu_f.add_command(label="Закрыть", command=lambda:close_file())
menu_f.add_command(label="Выход", command=my_w.quit)
my_w.config(menu=menubar) # adding menu to window

t1 = tk.Text(my_w, height=15, width=45) # added one text box
t1.grid(row=1,column=1,padx=30,pady=20)

my_w.mainloop()

Пример 16. Открыть, сохранить файл в Меню

Мы создадим наш первый пример строки меню, которая имеет File меню, как в большинстве редакторов. Мы включаем только Open, Save и Quit подменю для простоты.

Код 18_24 в папке 18

import tkinter as tk

app = tk.Tk()
app.geometry("300x200")
app.title("Basic Menu Bar")

menubar = tk.Menu(app)

filemenu = tk.Menu(menubar)
filemenu.add_command(label="Open")
filemenu.add_command(label="Save")
filemenu.add_command(label="Exit")

menubar.add_cascade(label="File", menu=filemenu)

app.config(menu=menubar)

app.mainloop()

menubar = tk.Menu(app)

Данный параметр Menu является родительским виджетом созданного меню. Строка кода выше означает, что виджет меню menubar будет верхним уровнем фрейма app.

filemenu = tk.Menu(menubar)

Аналогично, filemenu это меню виджета menubar или подменю фрейма app.

filemenu.add_command(label=”Open”)

add_command добавляет команды в меню filemenu. label— текст, отображаемый в подменю.

menubar.add_cascade(label=”File”, menu=filemenu)

filemenu добавляется к menubar команде add_cascade. File— это метка меню, отображаемая на верхнем уровне фрейма app.

app.config(menu=menubar)

Хотя menubar создан как дочерний виджет, app как мы объяснили выше, вам все равно нужно настроить его так, чтобы он был menu. App. В противном случае в графическом интерфейсе не будет отображаться строка меню.

Он вообще не реагирует, если вы нажимаете на опции типа Open или Save в подменю, File, потому что к ним пока не прикреплена команда.

Мы сделаем команду функциональной в следующем сеансе.

Код 18_25 в папке 18

import tkinter as tk
from tkinter import filedialog


def onOpen():
print(
filedialog.askopenfilename(
initialdir="/",
title="Open file",
filetypes=(("Python files", "*.py;*.pyw"), ("All files", "*.*")),
)
)


def onSave():
print(
filedialog.asksaveasfilename(
initialdir="/",
title="Save as",
filetypes=(("Python files", "*.py;*.pyw"), ("All files", "*.*")),
)
)


app = tk.Tk()
app.geometry("300x200")
app.title("Menu Bar Command")

menubar = tk.Menu(app)

filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Open", command=onOpen)
filemenu.add_command(label="Save", command=onSave)
filemenu.add_command(label="Exit", command=app.quit)

menubar.add_cascade(label="File", menu=filemenu)

app.config(menu=menubar)

app.mainloop()

filemenu = tk.Menu(menubar, tearoff=0)

tearoff установлено 1 по умолчанию и отсоединит меню от главного окна, чтобы создать плавающее меню, если нажать на пунктирные линии вверху. Здесь установлено 0 отключить эту плавающую функцию.

filemenu.add_command(label=”Open”, command=onOpen)

onOpen Функция привязана к меню Openи будет вызвана при Open щелчке по ней.

def onOpen():
print(
filedialog.askopenfilename(
initialdir="/",
title="Open file",
filetypes=(("Python files", "*.py;*.pyw"), ("All files", "*.*")),
)
)

Эта функция отображает диалог открытия и возвращает выбранное имя файла. В нашем примере мы на самом деле не открываем файл, а печатаем его имя.

Tkfiledialog имеет три функции,

Функция    Параметры Описание

.askopenfilename  Каталог, Название, Расширение      Чтобы открыть файл: диалоговое окно, предлагающее выбрать существующий файл.

.asksaveasfilename         Каталог, Название, Расширение      Для сохранения файла: диалоговое окно, запрашивающее создание или замену файла.

.askdirectory         Никто         Чтобы открыть каталог

filemenu.add_command(label=”Exit”, command=app.quit)

Tkinter имеет внутреннюю quit функцию, которая выходит из корневого GUI. Мы могли бы просто привязать эту существующую функцию к Exit вместо того, чтобы создавать свою собственную exit функцию.