Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ########################################################################################################################
- # File: menus.py
- # Purpose: Creates a menubar with submenus for Tkinter GUI
- # Author: Dan Huckson, https://github.com/unodan
- # Date: 2018-05-21
- ########################################################################################################################
- from tkinter import *
- def label_underline(label):
- position = label.find('&')
- if position >= 0:
- label = label[:position] + label[position + 1:]
- return label, position
- class MenuItem:
- def __init__(self, menu, item, **kwargs):
- self.__parent = menu
- self.__attributes = {}
- fg = self.__attributes['fg'] = kwargs.pop('fg', None)
- bg = self.__attributes['bg'] = kwargs.pop('bg', None)
- font = self.__attributes['font'] = kwargs.pop('font', None)
- activeforeground = self.__attributes['activeforeground'] = kwargs.pop('activeforeground', None)
- activebackground = self.__attributes['activebackground'] = kwargs.pop('activebackground', None)
- index = kwargs.pop('index', None)
- image = self.__attributes['image'] = item[1]
- accelerator = self.__attributes['accelerator'] = item[2]
- command = self.__attributes['command'] = None if len(item) < 4 and not len(item) > 4 else item[3]
- state = self.__attributes['state'] = 'normal' if len(item) < 5 else item[4]
- label, underline = label_underline(item[0])
- self.__attributes['label'] = self.__index = label
- if label == '--sep--':
- menu.add_separator()
- else:
- menu_command = menu.insert if isinstance(item[2], tuple) else menu.add_command
- menu_command(
- index=index,
- state=state,
- command=command,
- font=font,
- label=label,
- image=image,
- compound='left',
- foreground=fg,
- background=bg,
- underline=underline,
- accelerator=accelerator,
- activeforeground=activeforeground,
- activebackground=activebackground,
- )
- def cget(self, index):
- return self.__attributes.get(index, None)
- def config(self, **kwargs):
- fg = kwargs.pop('fg', None)
- if fg:
- self.__attributes['fg'] = fg
- bg = kwargs.pop('bg', None)
- if bg:
- self.__attributes['bg'] = bg
- font = kwargs.pop('font', None)
- if font:
- self.__attributes['font'] = font
- label = kwargs.pop('label', None)
- if label:
- self.__index = label
- self.__attributes['label'] = label
- image = kwargs.pop('image', None)
- if image:
- self.__attributes['image'] = image
- state = kwargs.pop('state', None)
- if state:
- self.__attributes['state'] = state
- underline = kwargs.pop('underline', None)
- if underline:
- self.__attributes['underline'] = underline
- accelerator = kwargs.pop('accelerator', None)
- if accelerator:
- self.__attributes['accelerator'] = accelerator
- activeforeground = kwargs.pop('activeforeground', None)
- if activeforeground:
- self.__attributes['activeforeground'] = activeforeground
- activebackground = kwargs.pop('activebackground', None)
- if activebackground:
- self.__attributes['activebackground'] = activebackground
- self.__parent.entryconfig(
- self.__index,
- font=font,
- label=label,
- image=image,
- state=state,
- compound='left',
- foreground=fg,
- background=bg,
- underline=underline,
- accelerator=accelerator,
- activeforeground=activeforeground,
- activebackground=activebackground,
- )
- class Menus(Menu):
- def __init__(self, parent, *args, **kwargs):
- super(Menus, self).__init__(parent, *args, **kwargs)
- self.__items = {}
- self.__parent = parent
- self.__index = kwargs.pop('index', None)
- def get(self, path):
- path = path.replace('\\', '/')
- if '/' in path:
- return self.item(self, path)
- return self.__items.get(path, None)
- def item(self, menu, path):
- parts = path.split('/', 1)
- member = menu.get(parts[0])
- if len(parts) > 1:
- member = self.item(member, parts[1])
- return member
- def set(self, index, value):
- if index in self.__items:
- self.__items[index] = value
- def get_items(self):
- return self.__items
- def add_items(self, item, **kwargs):
- label, underline = label_underline(item[0])
- if label in self.__items and label != '--sep--':
- return
- bd = kwargs.pop('bd', self.cget('bd'))
- fg = kwargs.pop('fg', self.cget('fg'))
- bg = kwargs.pop('bg', self.cget('bg'))
- font = kwargs.pop('font', self.cget('font'))
- tearoff = kwargs.pop('tearoff', self.cget('tearoff'))
- activeforeground = kwargs.pop('activeforeground', self.cget('activeforeground'))
- activebackground = kwargs.pop('activebackground', self.cget('activebackground'))
- index = kwargs.pop('index', self.__index)
- menu_command = SubMenu if isinstance(item[2], tuple) else MenuItem
- self.__items[label] = menu_command(
- self,
- item,
- bd=bd,
- fg=fg,
- bg=bg,
- font=font,
- index=index,
- tearoff=tearoff,
- activeforeground=activeforeground,
- activebackground=activebackground,
- )
- def populate(self, menus):
- if menus:
- for item in menus:
- self.add_items(item)
- class SubMenu(Menus):
- def __init__(self, parent, menu, *args, **kwargs):
- index = kwargs.pop('index', None)
- super().__init__(parent, *args, **kwargs)
- bd = kwargs.pop('bd', self.cget('bd'))
- fg = kwargs.pop('fg', self.cget('fg'))
- bg = kwargs.pop('bg', self.cget('bg'))
- font = kwargs.pop('font', self.cget('font'))
- tearoff = kwargs.pop('tearoff', self.cget('tearoff'))
- activeforeground = kwargs.pop('activeforeground', self.cget('activeforeground'))
- activebackground = kwargs.pop('activebackground', self.cget('activebackground'))
- image = menu[1]
- items = None if len(menu) < 3 and not len(menu) > 3 else menu[2]
- state = 'normal' if len(menu) < 4 else menu[3]
- self.__items = {}
- label, underline = label_underline(menu[0])
- menu_command = parent.add_cascade if index is None else parent.insert_cascade
- menu_command(index, label=label, image=image, compound='left', menu=self, state=state, underline=underline)
- item_names = []
- for item in items:
- if item[0] in item_names and item[0] != '--sep--':
- continue
- label = item[0]
- position = label.find('&')
- if position != -1:
- label = label[:position] + label[position + 1:]
- menu_command = SubMenu if isinstance(item[2], tuple) else MenuItem
- item_names.append(label)
- self.__items[label] = menu_command(
- self,
- item,
- bd=bd,
- fg=fg,
- bg=bg,
- font=font,
- tearoff=tearoff,
- activeforeground=activeforeground,
- activebackground=activebackground,
- )
- def get(self, path):
- path = path.replace('\\', '/')
- if '/' in path:
- return self.item(self, path)
- return self.__items.get(path, None)
- class MenuBar(Menus):
- def __init__(self, parent, *args, **kwargs):
- super().__init__(parent, *args, **kwargs)
- self.__items = {}
- class PopupMenu(Menus):
- def __init__(self, parent, *args, **kwargs):
- super().__init__(parent, *args, **kwargs)
- self.__items = {}
- self.__leave = False
- self.__delay_destroy = 1000
- self.bind("<Enter>", self.on_enter)
- self.bind("<Leave>", self.on_leave)
- self.bind("<Escape>", self.on_escape)
- def on_enter(self, event):
- self.__leave = False
- def on_leave(self, event):
- self.__leave = True
- def leave():
- if self.__leave:
- self.on_escape(event)
- self.after(self.__delay_destroy, leave)
- def on_escape(self, event):
- self.unpost()
- self.__leave = False
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement