By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,814 Members | 1,136 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,814 IT Pros & Developers. It's quick & easy.

Long Tkinter Menu

P: n/a
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).

As for why I'm creating such a long menu, think browser bookmarks
(That's not actually what I'm doing, but similar).

================================
# menu-example-5.py

from Tkinter import *

root = Tk()

menubar = Menu(root)

menu = Menu(menubar, tearoff=0)
for i in xrange(100):
menu.add_command(label=str(i), command=root.quit)
menu.add_command(label="Exit", command=root.quit)

menubar.add_cascade(label="Test", menu=menu)

root.config(menu=menubar)

mainloop()
================================

Oct 5 '06 #1
Share this Question
Share on Google+
2 Replies


P: n/a
On Thu, 05 Oct 2006 02:33:54 +0200, Dustan <Du**********@gmail.comwrote:
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+-'])"
Oct 5 '06 #2

P: n/a

Eric Brunel wrote:
On Thu, 05 Oct 2006 02:33:54 +0200, Dustan <Du**********@gmail.comwrote:
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+-'])"
Thanks, I'll see what I can do with that.

Oct 5 '06 #3

This discussion thread is closed

Replies have been disabled for this discussion.