[Tkinter-discuss] Execute Python callback from Tk widgets

Russell E. Owen rowen at uw.edu
Wed Oct 7 21:00:20 CEST 2009


In article <4ACCA070.3050603 at codebykevin.com>,
 Kevin Walzer <kw at codebykevin.com> wrote:

>...
> My question is this: how can I get Python callbacks to fire when a raw 
> Tk widget is being called via 'self.tk.call'? Do I have to write a fancy 
> wrapper that turns the widget into a Python object that will respond to 
> Python callbacks, or is there a simpler way to do this?

I use this class (from the RO package's module RO.TkUtil):

class TclFunc:
    """Register a python function as a tcl function.
    Based on Tkinter's _register method (which, being private,
    I prefer not to use explicitly).
    
    If the function call fails, a traceback is printed.
    
    Please call deregister when you no longer
    want the tcl function to exist.
    """
    tkApp = None
    def __init__(self, func, debug=False):
        if self.tkApp == None:
            self.tkApp =Tkinter.Frame().tk
        self.func = func
        self.tclFuncName = "pyfunc%s" % (id(self),)
        self.debug = bool(debug)
        try:
            self.tclFuncName += str(func.__name__)
        except AttributeError:
            pass
        if self.debug:
            print "registering tcl function %s for python function %s" % 
(self.tclFuncName, func)
        self.tkApp.createcommand(self.tclFuncName, self)
    
    def __call__(self, *args):
        try:
            self.func(*args)
        except (SystemExit, KeyboardInterrupt):
            raise
        except Exception, e:
            sys.stderr.write("tcl function %s failed: %s\n" % 
(self.tclFuncName, e))
            traceback.print_exc(file=sys.stderr)
        
    def deregister(self):
        """Deregister callback and delete reference to python function.
        Safe to call if already deregistered.
        """
        if self.debug:
            print "%r.deregister()" % (self,)
        if not self.func:
            if self.debug:
                print "already deregistered"
            return
        try:
            self.tkApp.deletecommand(self.tclFuncName)
        except Tkinter.TclError, e:
            if self.debug:
                print "deregistering failed: %r" % (e,)
            pass
        self.func = None
    
    def __repr__(self):
        return "%s(%s)" % (self.__class__.__name__, self.tclFuncName)
    
    def __str__(self):
        return self.tclFuncName



More information about the Tkinter-discuss mailing list