Long Tkinter Menu
Eric Brunel
eric_brunel at despammed.com
Thu Oct 5 04:01:13 EDT 2006
On Thu, 05 Oct 2006 02:33:54 +0200, Dustan <DustanGroups at gmail.com> wrote:
> I don't know if this is because of Tkinter (ie Tk) itself or the
> Windows default way of handling things, but when I create a very long
> menu (my test is shown below), the way it displays is rather sucky; the
> menu stretches from the top of the moniter's window to the bottom (no
> matter the size of the actual application).
>
> Is there any alternative format for how a long menu gets displayed? It
> would be nice if say, I could make the menu only go to the borders of
> the application itself (in this case, not that long).
To limit the menu in the application window, will be difficult. But here
are two ways of automatically limiting the number of entries that can
appear in a menu by specializing the Tkinter Menu class:
------------------------------------------------------
from Tkinter import *
class LongMenu(Menu):
"""
Automatically creates a cascade entry labelled 'More...' when the
number of entries is above MAX_ENTRIES.
"""
MAX_ENTRIES = 20
def __init__(self, *args, **options):
Menu.__init__(self, *args, **options)
self.nextMenu = None
def add(self, itemType, cnf={}, **kw):
if self.nextMenu is not None:
return self.nextMenu.add(itemType, cnf, **kw)
nbEntries = self.index(END)
if nbEntries < LongMenu.MAX_ENTRIES:
return Menu.add(self, itemType, cnf, **kw)
self.nextMenu = LongMenu(self)
Menu.add(self, 'cascade', label='More...', menu=self.nextMenu)
return self.nextMenu.add(itemType, cnf, **kw)
class AutoBreakMenu(Menu):
"""
Automatically adds the 'columnbreak' option on menu entries to make
sure that the menu won't get too high.
"""
MAX_ENTRIES = 20
def add(self, itemType, cnf={}, **kw):
entryIndex = 1 + (self.index(END) or 0)
if entryIndex % AutoBreakMenu.MAX_ENTRIES == 0:
cnf.update(kw)
cnf['columnbreak'] = 1
kw = {}
return Menu.add(self, itemType, cnf, **kw)
if __name__ == '__main__':
root = Tk()
menubar = Menu(root)
def fillMenu(menu):
for i in xrange(100):
menu.add_command(label=str(i), command=root.quit)
menu.add_command(label="Exit", command=root.quit)
menu1 = LongMenu(menubar, tearoff=0)
fillMenu(menu1)
menu2 = AutoBreakMenu(menubar, tearoff=0)
fillMenu(menu2)
menubar.add_cascade(label="Test1", menu=menu1)
menubar.add_cascade(label="Test2", menu=menu2)
root.config(menu=menubar)
root.mainloop()
------------------------------------------------------
If your application is more complicated than that (e.g if you insert menu
entries after the first adds), you'll have to change the code above a bit,
since it doesn't handle calls to insert at all. But you get the idea.
HTH
--
python -c "print ''.join([chr(154 - ord(c)) for c in
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"
More information about the Python-list
mailing list