I would like to pass both event and an additional argument to a handler function.
The purpose of this is to display a context menu using the x_root
and y_root
arguments of the event object.
I have tried the two techniques shown below. For simplicity, I prefer the one that uses the lambda function, but it doesn't work.
Is it possible to fix it? Any idea or explanation?
import tkinter as tk
class Example:
def __init__(self, window):
base = tk.Frame(window).pack()
for i in range(3):
l = tk.Label(base, text='label ' str(i))
l.pack()
def interhandler(event, self=self, i=i):
return self._handler_one(event, i)
l.bind("<Button-1>", interhandler)
l.bind("<Button-3>", lambda event, i=i: self._handler_two(i))
def _handler_one(self, event, k):
print(event) # works
print('left click on label', k)
def _handler_two(self, k):
print(event) # does not work
print('right click on label ', k)
main = tk.Tk()
example = Example(main)
main.mainloop()
CodePudding user response:
If you want to send both values then function should get both values
def _handler_two(self, event, k): # <--- event
print(event) # now it works
print('right click on label ', k)
And you should send both values
lambda event, i=i: self._handler_two(event, i) # <--- event
Full working code
import tkinter as tk
class Example:
def __init__(self, window):
base = tk.Frame(window).pack()
for i in range(3):
l = tk.Label(base, text='label ' str(i))
l.pack()
def interhandler(event, self=self, i=i):
return self._handler_one(event, i)
l.bind("<Button-1>", interhandler)
l.bind("<Button-3>", lambda event, i=i: self._handler_two(event, i)) # <--- event
def _handler_one(self, event, k):
print(event) # works
print('left click on label', k)
def _handler_two(self, event, k): # <--- event
print(event) # now it works
print('right click on label ', k)
main = tk.Tk()
example = Example(main)
main.mainloop()
CodePudding user response:
Issues: You have not passed the event argument when you invoke your _handler_two
callback function. Your callback function should also take two arguments, the event and the additional value.
Solution: Your code with the corrections can be found below:
import tkinter as tk
class Example:
def __init__(self, window):
base = tk.Frame(window).pack()
for i in range(3):
l = tk.Label(base, text='label ' str(i))
l.pack()
def interhandler(event, self=self, i=i):
return self._handler_one(event, i)
l.bind("<Button-1>", interhandler)
l.bind("<Button-3>", lambda event, i=i: self._handler_two(event, i))
def _handler_one(self, event, k):
print(event)
print('left click on label', k)
def _handler_two(self, event, k):
print(event)
print('right click on label ', k)
main = tk.Tk()
example = Example(main)
main.mainloop()
Sample Output: Below is the resulting window:
Below is the output after clicking the right mouse button on label 0:
<ButtonPress event state=Mod1 num=3 x=29 y=16>
right click on label 0
Alternatively: You can define your function to take a variable number of arguments:
def _handler_two(self, *args):
print(args[0])
print('right click on label ', args[1])