We're back after a server migration that caused effbot.org to fall over a bit harder than expected. Expect some glitches.

The tkList Widget Wrapper

Fredrik Lundh | March 2008

The tkList module is a simple wrapper for the Tkinter Listbox widget, which provides a somewhat more convenient API.

The wrapper adds two things: a vertical scrollbar, and a list-based API for populating and querying the widget. When adding data to the widget, the API lets you provide a custom mapping from list items to listbox entries, so you can often use an existing data structure right away.

Here’s a brief description of the extended API. For examples, see below.

setdata(sequence, render=str)

Adds the contents of the given sequence to the listbox. The sequence can be a list, tuple, or any iterable object. The widget makes a shallow copy of the sequence. If a second argument is given, it should be a callable object that maps sequence items to strings.

getdata()

Returns the list displayed by the widget. This is a reference to the list object used by the widget, so the list should not be modified, unless you’re passing the result back to setdata immediately.

getselection()

Returns the current selection, as a list of items from the sequence passed to setdata. To get a list of indices instead, use curselection.

curselection()

Returns the current selection, as a list of integer indexes. Note that this differs somewhat from the original Listbox implementation, where this method returns a list of strings instead.

Most standard Listbox methods work as usual, including things like size and the selection stuff. The insert method is disabled, however; to update the contents, use getdata to fetch the internal list, and setdata to replace it. The getdata method returns a shared list; it’s safe to modify it only if you’re passing the resulting list to setdata.

Note that you must pass in the renderer to every call to setdata. It’s almost always a good idea to update the widget in a single location in your program anyway, so this isn’t much of a problem in practice.

Downloading the Module

The tkList wrapper is available from the effbot.org SVN server. To use it, just download the file and put it somewhere on your Python path.

http://svn.effbot.org/public/stuff/sandbox/tkinter/tkList.py

Displaying Items

To create and populate the widget, just create the widget as usual, and call the setdata method with the data you want to display, and, where necessary, a function that converts list items to strings. This example shows how to create the widget:

import Tkinter as tk
import tkList

master = tk.Tk()

# create widget
w = tkList.List(master)
w.setdata(...) # see below
w.pack()

master.mainloop()

Here are some examples showing how to populate the widget. First, a plain list:

# populate with list of strings
data = ["Sweden", "Norway", "Finland"]
w.setdata(data)

Next, a rendered list.

# populate with list of arbitrary objects, w. renderer
data = range(10)
w.setdata(data, lambda x: (x+1) * "-")

You can also display arbitrary objects:

# populate with list of arbitrary objects
data = [Person(u"Anja"), Person(u"Göran")]
w.setdata(data, lambda item: item.name)

Finally, an example displaying a sorted dictionary:

# populate with dict mapping region names to station codes
# listbox displays region and station count
data = {
    u"South Sweden": [1, 2, 5, 10, 20],
    u"North Sweden": [3, 4, 8, 9, 14, 16]
    }
w.setdata(
    sorted(data.items(), key=lambda x: x.lower()),
    lambda item: "%s (%d)" % (item[0], len(item[1])
)

Selecting Items

To enable selection, use the standard selectmode option to set how items should be selected, and then use getselection to fetch the current selection. This method returns a subset of the list passed to setdata.

w = tkList.List(master, selectmode=tk.EXTENDED)
w.pack()

...

print w.getselection()

If you need the numeric indexes instead, use the curselection method instead of getselection.

Here’s a larger example:

import Tkinter as tk
import tkList

master = tk.Tk()

def callback():
    print "GET", w.getselection()
    print "CUR", w.curselection()

w = tkList.List(master, selectmode=tk.EXTENDED)
w.setdata(["line %d" % i for i in range(20)])
w.pack()

b = tk.Button(master, text="show selection", command=callback)
b.pack()

tk.mainloop()

This example lets you select items from the list, and click “show selection” to display the selection, as returned by getselection and curselection, respectively. Try changing EXTENDED to some other selection mode (e.g. BROWSE for single-item selections, or MULTIPLE for “check box” behaviour). See the Listbox documentation for details.