|
Hi I hope someone can help me with the following problem: I have attached a menu class which is part of a project I have written. As my main menu names can be multiple lines I am using the image facility, without text, of Menu. However I cannot get an accelerate key to work. Can anyone please assist me? --
Regards |
|
Phone: |
+27 (0)21-671-1866 |
|
Mobile: |
+27 (0)82-900-5260 |
|
Fax: |
+27 (0)86-262-1838 |
"""
SYNOPSIS
These is the Menu class used in TARTAN.
This file is part of Tartan Systems (TARTAN).
AUTHOR
Written by Paul Malherbe, <[email protected]>
COPYING
Copyright (C) 2004-2013 Paul Malherbe. Free use of this software is
granted under the terms of the GNU General Public License (GPL) as
published by the Free Software Foundation, either version 2 of the
License, or (at your option) any later version.
TARTAN is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY, without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with TARTAN, if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or view/download
it at http://www.gnu.org/licenses/gpl.txt
"""
from Tkinter import *
from PIL import Image, ImageDraw, ImageFont, ImageTk
def getUnderline(dic, txt, sav=False):
"""
dic = dictionary name to use
txt = text to find underline for
sav = keep existing underlined character
"""
if not txt:
return dic, 0
if sav and txt.count("_"):
return dic, txt.index("_")
pos = 0
for c in txt:
# If the label is Exit, try and make x the hot key
if txt == "Exit" and c == "E":
continue
if (ord(c) in range(65, 91) or ord(c) in range(97, 123)) and \
(dic.count(c.lower()) == 0 and \
dic.count(c.upper()) == 0):
dic.append(c)
pos = txt.index(c)
break
return pos
class TartanMenu:
"""
Use this to class to draw menus as follows:
Create a list of lists of MenuBar Items for example:
men = [["MM","Control", "Control Routines and exit"],
["MM","General", "General Ledger Menu"],
["MM","Creditors", "Creditor's Ledger Menu"],
["MM","Debtors", "Debtor's Ledger Menu"],
["MM","Stores", "Stores Ledger Menu"],
["MM","Help", "User's Manual and About","right"]]
Where the fields are as follows:
MM = Main Menu:
Menu Name
Detail
CM = Cascade Menu:
Parent Name
Menu Name
Detail
Create a list of lists of Menu Items for example:
mod = [["F","Control","tarCfg","Configure Tartan"],
["PNN","Control","co1010","Company Records"],
["F","Control","sysEnd","Exit Program"],
["CY","Control","l -l","Directory"]]
Where the fields are as follows:
Type F = Function
P123 where 1 = Requiring Company Number (Y/N)
2 = Requiring Period Selection (Y/N)
3 = Pass the User Name to the Module
Parent Menu Name
Program, Function or Command
Security Level
Prompt
Routine number if required for type P above
Draw the menus as follows:
menu = TartanMenu(usr, men, mod, ign, lvl, cmd)
mf = Tartan MainFrame
usr = User Name
men = Menues
mod = Modules
lvl = Security Level
cmd = Command to Execute on Selection
img = Background Image to Display
"""
def __init__(self, **args):
for arg in args:
exec "self.%s = args[arg]" % arg
self.setVariables()
def setVariables(self):
# Create a list of menues and a dictionary of modules
menues = []
self.moddic = {}
for m in self.mod:
if not self.lvl == None and m[3] > self.lvl:
continue
if m[1] not in menues:
menues.append(m[1])
if m[0][0] == "P":
mm = "mm_%s" % m[2][:2]
if mm not in menues:
menues.append(mm)
if len(m) == 6:
mod = "%s%s" % (m[2][:-1], m[5])
self.moddic[mod] = [m[0], m[4], m[5]]
else:
mod = "%s%s" % (m[2][:-1], 0)
self.moddic[mod] = [m[0], m[4], None]
else:
mod = m[2]
self.moddic[mod] = [m[0], m[4], None]
self.menues = []
for men in self.men:
if men[0] == "MM" and men[1] in menues:
self.menues.append(men)
elif men[2] in menues:
self.menues.append(men)
def drawMenu(self):
self.menubar = Menu(fg="black", bg="white", activebackground="black")
self.mf["menu"] = self.menubar
labs = {}
mwth = 0
for m in self.menues:
if m[0] == "MM":
if "mbar" in labs:
pass
else:
labs["mbar"] = []
exec "%s = Menu(self.menubar, tearoff=False)" % m[1]
pos = getUnderline(labs["mbar"], m[2])
img = self.createLabel(m[2], pos)
nam = m[2].split()[0].split("'")[0]
exec "image_%s = img" % nam
exec "self.menubar.add_cascade(image=img, menu=%s)" % m[1]
exec "cm1 = lambda event, self=self, menu=%s: "\
"self.postMenu(event, menu)" % m[1]
self.menubar.bind_all("<Alt_L><%s>" % m[2][pos].upper(), cm1)
self.menubar.bind_all("<Alt_L><%s>" % m[2][pos].lower(), cm1)
self.menubar.bind_all("<Escape>", self.unpostMenu)
mwth += img.width()
elif m[0] == "CM":
if m[1] in labs:
pass
else:
labs[m[1]] = []
exec "%s = Menu(%s, tearoff=False)" % (m[2], m[1])
pos = getUnderline(labs[m[1]], m[3])
exec '%s.add_cascade(label="%s", menu=%s, '\
'underline=pos)' % (m[1], m[3], m[2])
for m in self.mod:
if m[3] > self.lvl:
continue
if m[1] in labs:
pass
else:
labs[m[1]] = []
if m[0][0] == "P" and len(m) == 6:
rtn = int(m[5])
else:
rtn = None
if m[4] == "Quit":
exec "%s.add_separator()" % m[1]
pos = getUnderline(labs[m[1]], m[4])
cmd = (self.menubar.register(self.cmd), m[0], m[2], rtn)
#stk = m[2].lower()
#if stk in images:
# image = Image.open(images[stk])
#elif stk in aliases and os.path.isfile(aliases[stk]):
# image = Image.open(aliases[stk])
#else:
# image = None
image = None
if image:
image = image.resize((20, 20), 0)
exec "self.image%s = ImageTk.PhotoImage(image)" % stk
exec '%s.add_command(label="%s", command=cmd, underline=pos, '\
'image=self.image%s, compound="left")' % (m[1], m[4], stk)
else:
exec '%s.add_command(label="%s", command=cmd, underline=pos)' \
% (m[1], m[4])
self.mf.geometry("%sx%s" % (mwth, 200))
self.mf.mainloop()
def postMenu(self, event, menu):
menu.event_generate("<Enter>")
menu.event_generate("<Button-1>")
menu.event_generate("<Leave>")
#menu.post(event.x_root, event.y_root)
#self.posted = menu
#menu.focus_force()
def unpostMenu(self, event):
try:
self.posted.unpost()
except:
pass
def createLabel(self, text, pos):
unl = text[pos]
text = text.split()
if len(text) == 1:
text.insert(0, "")
elif len(text) == 3:
text[1] = "%s %s" % (text[1], text[2])
del text[2]
self.font = ImageFont.truetype("DejaVuSans-Bold.ttf", 12)
img = Image.new("RGBA", (70,30), (255,255,255))
self.draw = ImageDraw.Draw(img)
self.draw.text((0, 0),text[0],(0,0,0), font=self.font)
done = self.drawUnderline(text[0], unl, 14)
self.draw.text((0, 15),text[1],(0,0,0), font=self.font)
if not done:
self.drawUnderline(text[1], unl, 28)
return ImageTk.PhotoImage(img)
def drawUnderline(self, text, unl, y):
done = False
x = 0
for c in text:
if c == unl:
w = self.font.getsize(c)[0]
self.draw.line((x, y, x+w, y), fill=(0,0,0), width=1)
done = True
break
return done
def closeMenu(self, children=True):
self.menubar.destroy()
self.mf.quit()
if __name__ == "__main__":
def doNothing(m0, m2, rtn):
print m0, m2, rtn
if m2 == "sysEnd":
menu.closeMenu()
tk = Tk()
args = {
"mf": tk,
"men": [
["MM","mm_sy","System"],
["MM","mm_uy","General Utilities"],
["MM","mm_hp","Help","right"]],
"mod": [
["F","mm_sy","chgUsr",0,"Change User"],
["F","mm_sy","chgPwd",0,"Change Password"],
["F","mm_sy","tarUsr",7,"User's Maintenance"],
["F","mm_sy","sysUpd",0,"Upgrade System"],
["F","mm_sy","tarUpd",5,"Update File Formats"],
["PNNN","mm_sy","tb1040",9,"Copy Tables"],
["F","mm_sy","tarBck",0,"Backup Database"],
["F","mm_sy","tarRes",5,"Restore Database"],
["F","mm_sy","tarCfg",0,"Preferences"],
["F","mm_sy","sysEnd",0,"Quit"],
["PYNN","mm_uy","bm1010",0,"Bulk Mail/SMS Utility"],
["PNNN","mm_uy","fc1010",0,"Loan/Lease Calculator"],
["PNNY","mm_uy","pm1010",0,"Personal Password Manager"],
["PNNY","mm_uy","rp1010",2,"Report Generator"],
["PNNN","mm_uy","pw1010",0,"Server User Maintenance"],
["PNNY","mm_uy","td1010",0,"Telephone Directory"],
["PNNN","mm_uy","tp1010",5,"Template Manager"],
["F","mm_uy","showCal",0,"Calendar"],
["F","mm_hp","doAbout",0,"About"],
["F","mm_hp","doManual",0,"Manual"]],
"lvl": 9,
"cmd": doNothing}
menu = TartanMenu(**args)
menu.drawMenu()
_______________________________________________ Tkinter-discuss mailing list [email protected] http://mail.python.org/mailman/listinfo/tkinter-discuss
