Long Tkinter Menu

Dustan DustanGroups at gmail.com
Thu Oct 5 06:28:35 EDT 2006


Eric Brunel wrote:
> 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+-'])"

Thanks, I'll see what I can do with that.




More information about the Python-list mailing list