Tkinter Callbacks

This is a work in progress.

In Tkinter, a callback is Python code that is called by Tk when something happens. For example, the Button widget provides a command callback which is called when the user clicks the button. You also use callbacks with event bindings.

You can use any callable Python object as a callback. This includes ordinary functions, bound methods, lambda expressions, and callable objects. This document discusses each of these alternatives briefly.

Using Functions

In Python, functions are objects, and can be handled like any other object. The def statement creates an object and binds it to a name. To call the function, use the () operator on the object:

>>> def spam():
...    return "hello"
...
>>> spam
<function spam at 790a90>
>>> spam()
'hello'

To use a function object as a callback, pass it directly to Tkinter.

from Tkinter import *

def callback():
    print "clicked!"

b = Button(text="click me", command=callback)
b.pack()

mainloop()

For each function object, the Tkinter interface layer registers a Tk command with a unique name. When that Tk command is called by the Button implementation, the command calls the corresponding Python function.

If you’re curious, you can ask the widget for the name of the Tk command:

b = Button(text="click me", command=callback)
b.pack()

print b.cget("command")

This prints something like 9182704callback (that is, a unique integer followed by the function name).

Passing Argument to Callbacks

Tkinter’s Button widget doesn’t pass any information to the callback. This makes things a bit complicated if you want to use the same callback for several buttons, like in this example:

def callback():
    print "button", "?"

Button(text="one",   command=callback).pack()
Button(text="two",   command=callback).pack()
Button(text="three", command=callback).pack()

A common beginner’s mistake is to call the callback function when constructing the widget. That is, instead of giving just the function’s name (e.g. “callback”), the programmer adds parentheses and argument values to the function:

def callback(number):
    print "button", number

Button(text="one",   command=callback(1)).pack()
Button(text="two",   command=callback(2)).pack()
Button(text="three", command=callback(3)).pack()

If you do this, Python will call the callback function before creating the widget, and pass the function’s return value to Tkinter. Tkinter then attempts to convert the return value to a string, and tells Tk to call a function with that name when the button is activated. This is probably not what you wanted.

For simple cases like this, you can use a lambda expression as a link between Tkinter and the callback function:

def callback(number):
    print "button", number

Button(text="one",   command=lambda: callback(1)).pack()
Button(text="two",   command=lambda: callback(2)).pack()
Button(text="three", command=lambda: callback(3)).pack()

To be continued.

Scoping rules, binding to variable names or values, creating multiple function objects for the same function, etc.

Using Bound Methods

FIXME

from Tkinter import *

class Program:

    def __init__(self):
        b = Button(text="click me", command=self.callback)
        b.pack()

    def callback(self):
        print "clicked!"

program = Program()

mainloop()

Using Lambda Expressions

FIXME

Using Callable Objects

FIXME

 

A Django site. rendered by a django application. hosted by webfaction.