How to pass an argument to event handler in tkinter?
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.
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)
What about
import functools
def callback(self, event, param):
pass
arg = 123
widget.bind("", functools.partial(callback, param=arg))
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
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.
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)
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()
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.
精彩评论