How do I make Bind and Command do the same thing in tkinter?

2.2k views Asked by At

I have a tkinter GUI with an entry field and a validation button. I'd like to call the same function when I press a key in the entry, or when I click the button.

The problem is, with the bind method on the entry, I need a "self" argument for my function to work, but not with the button.

Here is the simplified code:

from tkinter import *
import tkinter.messagebox
import tkinter.filedialog


def function():
    print("Here are some words.")

my_window = Tk()

text = StringVar()
input_widget = Entry(my_window, textvariable = text) #We create an input widget.
input_widget.bind("<Return>", function)

benjamin = Button(my_window, text ='Print', command = function) #We create another widget, a 
# button that sends the same function as pressing <Return> key.

input_widget.grid(row = 0, column = 0) #We use grid to place our widgets.
benjamin.grid(row = 0, column = 1)


my_window.mainloop()

With this code, when I use the button, no problem, it prints, but when I use the bind, it returns:

Exception in Tkinter callback
Traceback (most recent call last):
File "C:\"blablabla"\tkinter\__init__.py, line 1533, in __call__
    return self.func(*args)
TypeError: function() takes 0 positionnal arguments but 1 was given

I can make it work by calling two functions one for the button, and another for the entry with a self argument:

def function2(self):
    print("It works with this function.")

Is there any way to make both .bind and command share the the same function?

2

There are 2 answers

0
maccartm On BEST ANSWER

Add this to your binding:

input_widget.bind("<Return>", lambda event: function())

Event bindings all require an event parameter which is automatically passed to the function. By using a lambda with the parameter event; you can take in this "event" variable and basically discard it and do whatever is in function()

2
Kevin On

You could write your function so that it takes any number of arguments:

def function(*args):
    #args is now a tuple containing every argument sent to this function
    print("Here are some words.")

Now you can successfully call the function with 0, 1, or any other number of arguments.


Alternatively, you could keep your function as it is, and use a lambda to discard the unused self value:

input_widget.bind("<Return>", lambda x: function())