Short answer: you cannot. Callbacks can't return anything because there's nowhere to return it to -- except the event loop, which doesn't do anything with return values.
In an event based application, what you typically will do is set an attribute on a class. Or, if you're a beginner, you can set a global variable. Using a global variable isn't a good idea for real code that has to be maintained over time but it's OK for experimentation.
So, for example, since C appears to be a global variable in your example, you would do something like:
def button():
global C
mylabel = Label(myGui, text = "hi").grid(row = 0, column = 0)
A = B.get()
C = A
Answer from Bryan Oakley on Stack OverflowShort answer: you cannot. Callbacks can't return anything because there's nowhere to return it to -- except the event loop, which doesn't do anything with return values.
In an event based application, what you typically will do is set an attribute on a class. Or, if you're a beginner, you can set a global variable. Using a global variable isn't a good idea for real code that has to be maintained over time but it's OK for experimentation.
So, for example, since C appears to be a global variable in your example, you would do something like:
def button():
global C
mylabel = Label(myGui, text = "hi").grid(row = 0, column = 0)
A = B.get()
C = A
You could call C.set from within the button function:
def button:
mylabel = Label(myGui, text = "hi").grid(row = 0, column = 0)
A = B.get()
C.set(A)
# return A # return values are useless here
Im making this app that need to delay before call a function and get the return value. but because of time.sleep is freezing tkinter gui so i used tkinter.after. tkinter.after is working and diddnt frezee the window, but i cannot get a return value of a function that i've called. because after i delayed and get the returned value, i've to return it again to the other function that called this function.
i've been struggling with this, please if any of u know any solutions, help me
this is the basic example of whats going on
import tkinter as tk
from time import sleep
def getvalue():
value = "haha"
sleep(3)
return value
def printvalue():
value = getvalue()
print(value)
app = tk.Tk()
app.geometry("500x300")
button = tk.Button(app, text="print value", command=printvalue)
button.pack()
app.mainloop()Say I have a function ask_for_number() which is called when a button is pressed. It creates a Toplevel window with a label that says 'Enter a number', an Entry widget, and a button that says 'Validate' which calls a function called validate_entry. validate_entry checks if a number is entered, using
try:
int(entry.get())
except TypeError:
# handle the errorbut because this is a different function the only way to access entry that I know of is to make it global first. I can't use 'return entry' and re-use the variable in validate_entry, because return doesn't work within tkinter mainloop (callbacks don't and can't return anything). What is the 'proper' way to do it without using globals?
The whole point of attaching a command to a button is to implement the answer to the question "what do I want to happen when I click the button?". In your case, the answer is "I want it to a) get the value from an entry widget, b) calculate a new value, and c) append it to a list".
So, write a function that does that, and then call that function from your button. In this case you don't need lambda since you have a 1:1 relationship between the button and entry widget. There's nothing wrong with lambda per se, but in this case it adds complexity without providing any value so I recommend not using it. By not using lambda, the code will be easier to debug and maintain over time since it's hard to set breakpoints or add additional functionality inside a lambda.
For example:
def f(x):
y=x**2
z=x-1
def do_calculation():
x_value = float(x.get())
result = f(x_value)
my_list.append(result)
...
tk.Button(..., command=do_calculation)
Use append(f(x)) in lambda and return [y,z] in f(x). And you have to convert string from Entry into int or float.
import tkinter as tk
# --- functions ---
def f(x):
x = int(x.get()) # convert string to int (or float)
y = x**2
z = x-1
return [y, z]
# --- main ---
my_list = []
master = tk.Tk()
e = tk.Entry(master)
e.pack()
cmd = lambda x=e:my_list.append(f(x))
tk.Button(master, text="Ok", command=cmd).pack()
master.mainloop()
print(my_list)
You can convert x in lambda and then f(x) could do only math calculations
EDIT: corrected version as @TadhgMcDonald-Jensen noted in the comment.
def f(x):
return [x**2, x-1]
#cmd = lambda x=int(e.get()):my_list.append(f(x)) # wrong version
cmd = lambda:my_list.append(f(int(e.get()))) # correect version
You can't really do that. The best way to do it is with a function but I'm not sure why you would want to do that. It seems a bit odd... As commented, the a Tkinter script runs differently to a normal Python script so nothing will be able to use the returned value. Store it as a variable if you need it.
I would just create a function that stores it as a variable.
def foo():
gah=entry.get()
# return entry.get()
# stuff or no stuff
button=Button(root, text="ghost", command=foo)
Long story short: How do I pass a variable by reference?
Example of a mutable object that persists after the callback
import tkinter as tk
from tkinter import messagebox
def function():
root = tk.Tk()
returned_values = {}
entry = tk.Entry(root)
entry.pack()
button = tk.Button(root, text = "I'm a button", command=lambda: callback(entry.get(), returned_values))
button.pack()
root.mainloop()
def callback(info, returned_values):
returned_values[len(returned_values)+1] = info
messagebox.showinfo('Success', f"Mutable: {returned_values}")
function()
As you can see, returned_values persists because it is a mutable object
Alright, so I am creating a small GUI program using tkinter, and one of the functions it performs requires a user to enter a document number. It then makes changes to the database based on the number entered, so I want to make sure the user entered it correctly.
To accomplish this, I am asking the user to enter the number again in a pop up window and then I compare the values and return True if they match or False otherwise.
I am having a hard time getting my def: to return the result of the lambda function inside of it.
I've tried assigning the lambda expression to a variable, but that seems to not return True or False as expected, but rather some internal Python stuff (memory addresses and such).
Am I trying to do this the right way? Is there a simpler way?
My code
If you use the class based approach to Tk applications, instead of returning values from event handlers, you can assign them to instance variables. This the best approach, as function-based GUI applications don't scale well precisely because the need to place stuff at module scope.
from Tkinter import *
class Application(Frame):
def main(self):
self.filename = askopenfilename(filetypes=[("Jpeg","*.jpg")])
def createWidgets(self):
self.button = Button(root,text="Open",command=self.main)
self.button.pack()
def __init__(self, master=None):
Frame.__init__(self, master)
self.filename = None
self.pack()
self.createWidgets()
root = Tk()
root.title("Image Manipulation Program")
app = Application(master=root)
app.mainloop()
Generally, it is bad practice to use global variables to pass information around your program. However, if you really must do this, use a mutable data type (such as a list or a dict) as your global variable and change its contents from your callback function, main.
returned_values = {} # Create an empty dict.
def main():
returned_values['filename'] = askopenfilename(filetypes=[("Jpeg","*.jpg")])
# returned_values['filename'] may now be accessed in the global scope.
If you intend to do this frequently, consider implementing your own class to pass information around.
