Tkinter Widget Overview
  Copyright © 1997 by Fredrik Lundh <[email protected]>  
  Updated 9 Nov 1997  

The Listbox Widget

The Listbox widget is a standard Tkinter widget used to display a list of alternatives. The listbox can only contain text items, and all items must have the same font and color. Depending on the widget configuration, the user can choose one or more alternatives from the list.

Listbox Patterns

When you first create the listbox, it is empty. The first thing to do is usually to insert one or more lines of text. The insert method takes an index and a string to insert. The index is usually an item number (0 for the first item in the list), but you can also use some special indices, including ACTIVE, which refers to the "active" item (set when you click on an item, or by the arrow keys), and END, which is used to append items to the list.

listbox = Listbox(master)
listbox.insert(END, "a list entry")
for item in ["one", "two", "three", "four"]:
    listbox.insert(END, item)

To remove items from the list, use the delete method. The most common operation is to delete all items in the list (something you often need to do when updating the list).

listbox.delete(0, END)
listbox.insert(END, newitem)

You can also delete individual items. In the following example, a separate button is used to delete the ACTIVE item from a list.

lb = Listbox(master)
b = Button(master, text="Delete",
           command=lambda lb=lb: lb.delete(ANCHOR))

The listbox offers four different selection modes through the selectmode option. These are SINGLE (just a single choice), BROWSE (same, but the selection can be moved using the mouse), MULTIPLE (multiple item can be choosen, by clicking at them one at a time), or EXTENDED (multiple ranges of items can be chosen, using the Shift and Control keyboard modifiers). The default is BROWSE. Use MULTIPLE to get "checklist" behaviour, and EXTENDED when the user would usually pick only one item, but sometimes would like to select one or more ranges of items.

lb = Listbox(selectmode=EXTENDED)

To query the selection, use the curselection method. It returns a list of item indices, but a bug in Tkinter 1.63 and earlier causes this list to be a list of strings, instead of integers. Since this will be fixed in future versions of Tkinter, you should make sure your code are written to handle either case. Here's one way to do that:

items = list.curselection()
try:
    items = map(string.atoi, items)
except ValueError: pass

You can use eval instead of string.atoi, but that's slightly slower. Use the get method to get the list item corresponding to a given index.

You can easily use a list to represent arbitrary Python objects. In the next example, we assume that the input data is represented as a list of tuples, where the first item in each tuple is the string to display in the list. For example, you could display a dictionary by using the items() method to get such a list.

self.lb.delete(0, END) # clear
for item in data:
    self.lb.insert(END, item[0])
self.data = data

When querying the list, simply fetch the items indexed by the selection list:

items = self.lb.curselection()
try:
    items = map(string.atoi, items)
except ValueError: pass
items = map(lambda i,d=self.data: d[i], items)

Unfortunately, the listbox doesn't provide a command option allowing you to track changes to the selection. The standard solution is to bind a doubleclick event to the same callback as the OK (or Select, or whatever) button. This allows the user to either select an alternative as usual, and click OK to carry out the operation, or to select and carry out the operation in one go by double-clicking on an alternative. This solution works best in BROWSE and EXTENDED modes.

	lb.bind("<Double-Button-1>", self.ok)

If you wish to track arbitrary changes to the selection, you can either rebind the whole bunch of selection related events (see the Tk manual pages for a complete list of Listbox event bindings), or, much easier, poll the list using a timer:

def __init__(self, master):
    self.list = Listbox(selectmode=EXTENDED)
    self.list.pack()
    self.current = None
    self.poll() # start polling the list
def poll(self):
    now = self.list.curselection()
    if now != self.current:
        self.list_has_changed(now)
        self.current = now
    self.after(250, self.poll)

By default, the selection is exported to the X selection mechanism. If you have more than one listbox on the screen, this really messes things up for the poor user. If he selects something in one listbox, and then selects something in another, the original selection is cleared. It is usually a good idea to disable this mechanism in such cases. In the following example, three listboxes are used in the same dialog:

b1 = Listbox(exportselection=0)
for item in families:
    b1.insert(END, item)
b2 = Listbox(exportselection=0)
for item in fonts:
    b2.insert(END, item)
b3 = Listbox(exportselection=0)
for item in styles:
    b3.insert(END, item)

The listbox itself doesn't include a scrollbar. Attaching a scrollbar is pretty straightforward. Simply set the xscrollcommand and yscrollcommand options of the listbox to the set method of the corresponding scrollbar, and the command options of the scrollbars to the corresponding xview and yview methods in the listbox. Also remember to pack the scrollbars before the listbox. In the following example, only a vertical scrollbar is used. For more examples, see pattern section in the Scrollbar description.

frame = Frame(master)
scrollbar = Scrollbar(frame, orient=VERTICAL)
listbox = Listbox(frame, yscrollcommand=scrollbar.set)
scrollbar.config(command=listbox.yview)
scrollbar.pack(side=RIGHT, fill=Y)
listbox.pack(side=LEFT, fill=BOTH, expand=1)

With some more trickery, you can use a single vertical scrollbar to scroll several lists in parallel. This assumes that all lists have the same number of items. Also note how the widgets are packed in the following example.

def __init__(self, master):
    scrollbar = Scrollbar(master, orient=VERTICAL)
    self.b1 = Listbox(master, yscrollcommand=scrollbar.set)
    self.b2 = Listbox(master, yscrollcommand=scrollbar.set)
    scrollbar.config(command=self.xview)
    scrollbar.pack(side=RIGHT, fill=Y)
    self.b1.pack(side=LEFT, fill=BOTH, expand=1)
    self.b2.pack(side=LEFT, fill=BOTH, expand=1)
def xview(self, *args):
    apply(self.b1.xview, args)
    apply(self.b2.xview, args)

Methods

The Listbox widget supports the standard Tkinter Widget interface, plus the following methods:

activate(index). Activate the given index (it will be marked with an underline). The active item can be refered to using the ACTIVE index.

bbox(index). Get the bounding box of the given item text. The bounding box is returned as a 4-tuple giving (xoffset, yoffset, width, height). If the item is not visible, this method returns None.

curselection(). Get a list of the currently selected alternatives. The list contains the indices of the selected alternatives (beginning with 0 for the first alternative in the list). In Tkinter 1.63, the list contains strings instead of integers. Since this will probably be changed in future versions, make sure to write robust code. See the patterns section for a suggested solution.

delete(index) or delete(first, last). Delete one or more items. Use delete(0, END) to delete all items in the list.

get(index) or get(first, last). Get one or more items from the list. This function returns the string corresponding to the given index (or the strings in the given index range). Use get(0, END) to get a list of all items in the list. Use ACTIVE to get the active (underlined) item.

index(index). Return the numerical index (0 to size()-1) corresponding to the given index. This is typically ACTIVE, but can also be ANCHOR, or a string having the form "@x,y" where x and y are widget-relative pixel coordinates.

insert(index, items). Insert one or more items at given index (this works as for Python lists; index 0 is before the first item). Use END to append items to the list. Use ACTIVE to insert items before the the active (underlined) item.

nearest(y). Return the index nearest to the given coordinate (a widget-relative pixel coordinate).

scan_mark(x, y), scan_dragto(x, y). Start and perform a scroll operation. Used by the standard mouse bindings. The coordinates are widget-relative pixel coordinates.

see(index). Make sure the given list index is visible. You can use an integer index, or END.

select_adjust(index). Extend the selection to include the given index.

select_anchor(index). Set the selection anchor to the given index. The anchor can be refered to using the ANCHOR index.

select_clear(). Clear the selection.

select_includes(index). Returns true if the given item is selected.

select_set(index) or select_set(first, last). Add one or more items to the selection.

size(). Return the number of items in the list. The valid index range goes from 0 to size()-1.

xview(), yview(). Determine which part of the full list that is visible in the horizontal (vertical) direction. This is given as the offset and size of the visible part, given in relation to the full size of the list (1.0 is the full list). These methods are used by the Scrollbar bindings.

xview(column), yview(index). Adjust the list so that the given character column (list item) is at the left (top) edge of the listbox. To make sure that a given item is visible, use the see method instead.

xview_moveto(offset), yview_moveto(offset). (Not in Tkinter 1.63). Adjust the list so that the given offset is at the left (top) edge of the listbox. Offset 0.0 is the beginning of the list, 1.0 the end. These methods are used by the Scrollbar bindings. In Tkinter 1.63, use xview("moveto", offset) and yview("moveto", offset) instead.

xview_scroll(step, what), yview_scroll(step, what). (Not in Tkinter 1.63). Scroll the list horizontally (vertically) by the given amount. The what argument can be either "units" (lines) or "pages". These methods are used by the Scrollbar bindings. In Tkinter 1.63, use xview("scroll", step, what) and yview("moveto", step, what) instead.

Options

Option Type Description
background, foreground color The listbox color. The default is platform specific.
borderwidth or bd int The width of the listbox border. The default is platform specific, but is usually 1 or 2 pixels.
cursor cursor name The cursor to show when the mouse is moved over the listbox.
exportselection bool If set, the list selection is automatically exported via the X selection mechanism. The default is on. If you have more than one list in the same dialog, it is probably best to disable this mechanism.
font font The font to use in the listbox. The listbox can only contain text in a single font.
relief constant Listbox border relief.
selectbackground, selectforeground color Selection color settings.
selectborderwidth int Selection border width. The selection is always raised.
selectmode constant Selection mode. One of SINGLE, BROWSE, MULTIPLE, or EXTENDED. Default is BROWSE. Use MULTIPLE to get checklist behaviour, EXTENDED if the user usually selects one item, but sometimes would like to select one or more ranges of items. See the patterns section for more information.
setgrid bool  
takefocus bool Indicates that the user can use the Tab key to move to this listbox. Default is on.
width, height int The size of the listbox, in text units.
xscrollcommand, yscrollcommand command Used to connect a listbox to a scrollbar. These options should be set to the set methods of the corresponding scrollbars.