43
widget.bind('<Button-1>',callback)   # binding 

def callback(self,event)
    #do something

I need to pass an argument to callback() . The argument is a dictionary object.

2
  • You want to pass it from the binding, or when the callback is done ? Commented Jul 21, 2010 at 7:05
  • i should pass an argument when the callback is done Commented Jul 21, 2010 at 7:26

7 Answers 7

72

You can use lambda to define an anonymous function, such as:

data={"one": 1, "two": 2}

widget.bind("<ButtonPress-1>", lambda event, arg=data: self.on_mouse_down(event, arg))

Note that the arg passed in becomes just a normal argument that you use just like all other arguments:

def on_mouse_down(self, event, arg):
    print(arg)
Sign up to request clarification or add additional context in comments.

2 Comments

then how to access that arg in the event handler? what should be the declaration of the handler
@sag: see my edit. Short answer: you access it like any other argument.
16

What about

import functools
def callback(self, event, param):
    pass
arg = 123
widget.bind("", functools.partial(callback, param=arg))

5 Comments

giving Exception: leftClickCallback() got an unexpected keyword argument 'param'
Does your callback as the param argument? This works ok form me.
self.l.bind("<Button-1>", functools.partial(self.leftClickCallback,param=fi)) this is the bind step.whats wrong here?
How is the leftClickCallback method declared?
def leftClickCallback(self,event,param):
4

I think that in most cases you don't need any argument to a callback because the callback can be an instance method which can access the instance members:

from Tkinter import *

class MyObj:
    def __init__(self, arg):
        self.arg = arg

    def callback(self, event):
        print self.arg

obj = MyObj('I am Obj')
root = Tk()
btn=Button(root, text="Click")
btn.bind('<Button-1>', obj.callback)
btn.pack()
root.mainloop()

But I think the functools solution proposed by Philipp is also very nice

1 Comment

That only works if the objects you're trying to access are in the global scope (or more specifically, in the same scope as the callback function)
2

Here is an entry on this from the New Mexico Tech Tkinter 8.5 Reference (https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/extra-args.html) ‌‌‌‌‍‬‍‌‌‌‌‍‬‬‍‌‌‌‌‍‬‌‬‌‌‌‌‍‬‌‬‌‌‌‌‍‬‍‍‌‌‌‌‍‌‬‌‌‌‌‍‬‬‍‌‌‌‌‍‌‌‌‌‌‍‬‬‌‌‌‌‌‍‬‍‌‌‌‌‍‬‬‍‌‌‌‌‍‬‌‬‌‌‌‌‍‬‌‬‌‌‌‌‍‬‍‍‌‌‌‌‍‌‬‌‌‌‌‍‬‬‍‌‌‌‌‍‌‌‌‌‌‍‬‬‌

‌‌‌‌‍‬‍‌‌‌‌‍‬‬‍‌‌‌‌‍‬‌‬‌‌‌‌‍‬‌‬‌‌‌‌‍‬‍‍‌‌‌‌‍‌‬‌‌‌‌‍‬‬‍‌‌‌‌‍‌‌‌‌‌‍‬‬‌

This way allows you to add as many arguments as you need:

‌‌‌‌‍‬‍‌‌‌‌‍‬‬‍‌‌‌‌‍‬‌‬‌‌‌‌‍‬‌‬‌‌‌‌‍‬‍‍‌‌‌‌‍‌‬‌‌‌‌‍‬‬‍‌‌‌‌‍‌‌‌‌‌‍‬‬‌

54.7. The extra arguments trick

Sometimes you would like to pass other arguments to a handler besides the event.

Here is an example. Suppose your application has an array of ten checkbuttons whose >widgets are stored in a list self.cbList, indexed by the checkbutton number in >range(10).

Suppose further that you want to write one handler named .__cbHandler for >events in all ten of these checkbuttons. The handler can get the actual Checkbutton >widget that triggered it by referring to the .widget attribute of the Event object that >gets passed in, but how does it find out that checkbutton's index in self.cbList?

It would be nice to write our handler with an extra argument for the checkbutton number, >something like this:

def __cbHandler(self, event, cbNumber):

But event handlers are passed only one argument, the event. So we can't use the function >above because of a mismatch in the number of arguments.

Fortunately, Python's ability to provide default values for function arguments gives us >a way out. Have a look at this code:

def __createWidgets(self):
    …
    self.cbList = []    # Create the checkbutton list
    for i in range(10):
        cb = tk.Checkbutton(self, …)
        self.cbList.append(cb)
        cb.grid( row=1, column=i)
        def handler(event, self=self, i=i):   1
            return self.__cbHandler(event, i)
        cb.bind('<Button-1>', handler)
    …
def __cbHandler(self, event, cbNumber):
    …

These lines define a new function handler that expects three arguments. The first >argument is the Event object passed to all event handlers, and the second and third >arguments will be set to their default values—the extra arguments we need to pass it.

This technique can be extended to supply any number of additional arguments to >handlers.

1 Comment

This is not a solution, you have to hardcode your arguments in the same scope as the callback function
2

How to pass an argument to event handler in tkinter?

Here is the simplest and easiest-to-read solution of them all I think:

widget.bind('<Button-1>', callback2)

# change "None" to whatever you want the default value to be
def callback(self, event, custom_arg=None): 
    # do something
    
def callback2(self, event):
    # set custom_arg to whatever you want it to be when Button-1 is pressed
    callback(event, custom_arg=something_you_set) 

2 Comments

Probably because, you did in two steps what you could have done in one. Just my opinion.
Regardless of whether the deletion of your comment was an unlucky incident or not, it added nothing to topic being discussed and @Ishrak's comment is likely true. Simply being the "simplest and easiest-to-read" do not a good answer make. For example, consider that adding two to a variable could be accomplished by doing v = v + 1 twice in a row or more succinct and efficiently in single statement via v += 2 — which is "better"?
1

Pass the callback function to the instance and call it from the instance method.

from tkinter import *

class MyClass:

    def __init__(self, my_callback, message):
        self.my_callback = my_callback
        self.message = message

    def callback(self, event):
        self.my_callback(self)

def my_callback(o):
    print(o.message)


obj = MyClass(my_callback, "I am instance of MyClass")

root = Tk()

btn=Button(root, text="Click")
btn.bind('<Button-1>', obj.callback)
btn.pack()

Comments

0

You can also supply arguments to a callback function of a widget, given only that this widget is defined as a part of a class definition ,, i.e. consider this tiny python 2.7 program (without the parts responsible of program's execution):

import Tkinter as tk #To be able to get "tk.Button" safely
from Tkinter import *

class EXAMPLE(Frame):
    def __init__(self,master=None):
        Frame.__init__(self,master)

        #make the widgets appear to a grid of size = 2 X 2
        for row in range(2):
            self.grid_rowconfigure(row,minsize=20)
        for col in range(2):
            self.grid_columnconfigure(col,minsize=20)

        #Call our METHOD OF INTEREST
        self.AnyMethod()

    #This is our method of interest
    def AnyMethod(self):
        #arguments to be supplied
        self.arg1 = 'I am 1st argument'
        self.arg2 = 'I am 2nd argument'
        self.arg3 = 'I am 3rd argument'

        #Draw the widget, & supply its callback method
        self.widgetname=tk.Button(self.master,text="My Button",command=self.method_callback)
        self.widgetname.grid(row=0,column=0)

    #create a so-called 'shell method' to swallow the REAL callback function
    def method_callback(self):
        func_callback(self.arg1,self.arg2,self.arg3)

#Define the REAL callback function in the Module's scope
def func_callback(arg1,arg2,arg3):
    print arg1
    print arg2
    print arg3

NOTE THAT the supplied arguments must be proceeded with self.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.