Creating a pull-down list with Tkinter

Michael P. Reilly arcege at shore.net
Wed May 5 18:18:19 EDT 1999


Ben Gertzfield <che at debian.org> wrote:
: After reading through the meagre documentation available for Tkinter,
: I've stumped myself. Is there any module available that will give
: me a pull-down list, similar to what appears in tkFileDialog, or
: any of the zillions of pull-down lists you see on web pages?

: I'm trying to make a graphical front-end to my ID3 MP3 info tag
: manipulator Python class, but Listbox is inappropriate when there
: are ~150 selections possible for one of the fields (the genre
: of the song) and I need to let the user select from one of them.

: How can I create a pull-down list with Tkinter?

I'm not sure if you mean a scrolled listbox or an extensible menu button.

I've created the latter (based a bit on a similar widget in tkdiff in
the TkCVS package).

#!/usr/local/bin/python

from Tkinter import *
import os

class Popup(Menubutton):
  def __init__(self, master=None, list=None):
    Menubutton.__init__(self, master, direction='right', relief=RAISED)
    menu = self['menu'] = Menu(self)
    l = len(list)
    if l <= 10:
      for p in xrange(l):
        item = list[p]
        menu.add_command(label='%d %s' % (p+1, str(item)))
    else:
      from math import sqrt
      per_level = int(sqrt(l))
      how_many, extra = divmod(l, per_level)
      if extra:
        how_many = how_many + 1
      p = 0
      for i in xrange(how_many):
        submenu = Menu(self)
        menu.add_cascade(label=`(i*per_level)+1`, menu=submenu)
        for j in xrange(min(l-p, per_level)):
          item = list[p]
          submenu.add_command(label='%d %s' % (p+1, str(item)))
          p = p + 1

if __name__ == '__main__':
  m = Popup(None, os.listdir(os.environ['HOME']))
  m['text'] = 'What?'
  Button(text='Quit', command=m.quit).pack()
  m.pack()
  m.mainloop()

This creates a simple button which when pressed gives you a pop-up menu
of your home directory.  If you have more than ten files in your home
directory, then you will get a submenu for each N files.  The widget
isn't complete, but it suffices.

If you wanted a scrolled listbox, that is a bit easier:

class ScrolledListbox(Listbox):
  def __init__(self, master, cnf={}, **kw):
    from Tkinter import _cnfmerge
    if kw:
      cnf = _cnfmerge((cnf, kw))
    else:
      cnf = _cnfmerge(cnf)
    frame = Frame(master, cnf)
    Listbox.__init__(self, frame, relief=SUNKEN)
    scroll = Scrollbar(master, relief=SUNKEN, command=self.yview)
    scroll.pack(side=RIGHT, fill=Y, expand=YES)
    self['yscrollcommand'] = scroll.set
    self.pack(fill=BOTH, expand=YES)
    # redefine "pack", "place" and "grid" to be the frame instance's methods
    self.pack = frame.pack
    self.place = frame.place
    self.grid = frame.grid

Now use instances of ScrolledListbox as a regular listbox.

  -Arcege





More information about the Python-list mailing list