The command lambda does not take any arguments at all; furthermore there is no evt that you can catch. A lambda can refer to variables outside it; this is called a closure. Thus your button code should be:
bouton1 = Button(main_window, text="Enter",
command = lambda: get(Current_Weight, entree1))
And your get should say:
def get(loot, entree):
loot = float(entree.get())
print(loot)
Answer from Antti Haapala on Stack OverflowThe command lambda does not take any arguments at all; furthermore there is no evt that you can catch. A lambda can refer to variables outside it; this is called a closure. Thus your button code should be:
bouton1 = Button(main_window, text="Enter",
command = lambda: get(Current_Weight, entree1))
And your get should say:
def get(loot, entree):
loot = float(entree.get())
print(loot)
Actually, you just need the Entry object entree1 as the lamda pass-in argument. Either statement below would work.
bouton1 = Button(main_window, text="Enter", command=lambda x = entree1: get(x))
bouton1 = Button(main_window, text="Enter", command=lambda : get(entree1))
with the function get defined as
def get(entree):
print(float(entree.get()))
Tkinter: pass reference to self to lambda function?
python - What's the importance of lambda functions in tkinter? - Stack Overflow
Tkinter button command using lambda to call a class method - how???
python - Using lambda function in command of Button widget in tkinter - Stack Overflow
Videos
When you use () with a function name(func(args)), then it is immediately calling/invoking the function while python is executing the line, you do not want that. You want to ONLY call the function when the button is clicked. tkinter will internally call the function for you, all you have to do is give the function name.
Why use lambda? Think of it as a function that returns another function, your code can be lengthened to:
func = lambda: comando_click("Nova_Mensagem")
botao = Button(menu_inicial, text = "Executar", command=func)
func is the function name and if you want to call it, you would say func(). And when you say command=comando_click("Nova_Mensagem") then command has the value returned by command click(because you call the function with ()), which is None and if I'm not wrong, if the given value is None, it will not be called by tkinter. Hence your function is executed just once because of () and as a result of calling the function, you are assigning the value of the function call(None) before the event loop starts processing the events.
Some other methods:
- Using
partialfromfunctools:
from functools import partial
botao = Button(.....,command=partial(comando_click,"Nova_Mensagem"))
- Using a helper function:
def helper(args):
def comando_click():
print(args)
return comando_click
botao = Button(...., command=helper("Nova_Mensagem"))
IMO, lambdas are the easiest way to proceed with calling a function with arguments.
In this code:
command=comando_click("Nova_Mensagem")
you have called the comando_click function, once, and assigned the result (None) to the command argument. Nothing will happen when command is called (in fact you should get a TypeError exception because None is not callable).
In this code:
command=lambda:comando_click("Nova_Mensagem")
you have not actually called comando_click yet -- you have created a new function (using lambda) that will in turn call comando_click when it is called. Every time the button is clicked, your new function will get called.
If the lambda is confusing, you can do the exact same thing with a def like this:
def button_command():
comando_click("Nova_Mensagem")
...
command=button_command # no ()! we don't want to actually call it yet!
The lambda expression is just an alternative to using def when you want to create a small single-use function that doesn't need a name (e.g. you want to make a function that calls another function with a specific argument, exactly as you're doing here).
Early days on Tkinter for me and I'm struggling with something.
I have several buttons that I want to all call the same function when clicked but then determine what task to perform within that function based on which of the buttons was actually clicked.
One way I managed it was to pass a string to the lambda function e.g.
button.command=lambda clickFunction('red')
then:
def clickFunction(buttonColor):
etc.
but is there a way I can pass 'self' in the lambda function so that I could do it a different way e.g.
button.color = 'red'
button.command=lamda clickFunction(self)
then:
def clickFunction(self):
print("Button colour is " + self.color
this doesn't work but it can be sort of made to work by passing the button itself:
button.command=lambda clickFunction(button)
but I don't necessarily want to do that and am curious if there's a way to pass 'self' to the function instead as that strikes me as more flexible (especially as I'm trying to write a class to create buttons by passing a set of parameters to the button constructor so that when I have many buttons to create I don't have to type the same button construction code out multiple times. Forgive me if this approach is wrong too! 🤣
I think I've read several hundred articles and Stackoverflow posts now but I can't seem to find the answer.
Can anyone explain to me the importance of the lambda function when creating interface with Tkinter?
Arguably, they aren't important at all. They are just a tool, one of several that can be used when binding widgets to functions.
The problem with the binding in your question is due to the fact that when you use bind to bind an event to a function, tkinter will automatically pass an event object to that function you must define a function that accepts that object.
This is where lambda comes in. The command needs to be a callable. One form of a callable is simply a reference to a function such as the one you're using (eg: command=self.concluir_return). If you don't want to modify your function to accept the parameter you can use lambda to create an anonymous function -- a callable without a name.
So, for your specific case, you can define a lambda that accepts the argument, and then the lambda can call your function without the argument.
But all was solved when I looked into web and modified the line of code with the lambda function.
self.master.bind("<Return>", lambda event: self.concluir_return())
This works because the code is effectively the same as if you did this:
def i_dont_care_what_the_name_is(event):
self.concluir_return()
self.master.bind("<Return>", i_dont_care_what_the_name_is)
As you can see, lamda isn't required, it's just a convenient tool that lets you create a simple function on the fly that calls another function.
The bind method takes two arguments, sequence and handler, and will call f(event) when the specified event occurs.
In your case, concluir_return wasn't expecting any argument other than self, so your code raised an error when it was called with event.
The lambda function you used is the equivalent of:
def f(event):
return concluir_handler()
so it bypasses the problem by just ignoring the event argument.
Another way of doing this would be to add an argument to concluir_return.
I'm stuck, what am I missing?
Not sure if it's classes or tkinter that I don't correctly understand.
If I run the example below and hit the button I get "missing argument (self)". I totally get that.
class MainWidget:
root = Tk()
root.geometry("400x400")
def open_notebook(self):
self.search_function.get_emp_id()
# and more stuff to add later
search_frame = Frame(root)
search_frame.pack()
search_function = SearchFunction(search_frame)
open_notebook_button = Button(root, text="Open", command=open_notebook)
open_notebook_button.pack()
root.mainloop()Then I tried:
command=lambda: open_notebook()
... but it doesn't know open_notebook.
command=lambda: self.open_notebook()
... it doesn't know self
command=lambda: root.open_notebook()
... and it doesn't know root.
As I am playing around more with this I realize I have no idea if I maybe need a contructor and what difference exactly that would make, what goes in it (no pun intended) and what doesn't. I have no experience with OOP beyond the very very basics.
I'm grateful for any advice!
The command argument requires a function with no positional arguments, so using lambda x: <do-something> will raise an error. In this case none of the arguments need to be passed during the callback and so you should simplify things to
def show_description():
key = int(code_entry.get())
if key in dictio:
textEntry.set(dictio[key])
else:
messagebox.showinfo("Info", "The number is not in the database")
show_button = Button(root, text="Mostrar descripción", command=show_description)
Also, doing this
dictio[int(code_entry.get())]
the way you did could have raised a KeyError after fixing the lambda having no arguments.
from tkinter import *
from tkinter import messagebox
root=Tk()
dictio={1:"one", 2:"two"}
test=False
textEntry = StringVar()
display=StringVar()
def show_description():
print(display.get()) #==get the value of the stringvat
x=int(display.get()) #==convert the value to integer
if dictio.get(x)==None:
messagebox.showinfo("Info", "The number is not in the database")
else:
textEntry.set(dictio.get(x)) #==get the value of the key from dictio dictionary and set it for description_entry
code_entry = Entry(root,textvariable=display)
display.set("") #==set value as nothing
code_entry.grid(row=1, column=1, sticky='nsew')
description_entry = Entry(root, state="disabled", textvariable = textEntry)
description_entry.grid(row=0, column=1, sticky='nsew')
show_button = Button(root, text="Mostrar descripción", command=show_description)
show_button.grid(row=0, column=2)
root.mainloop()