The notion of "returning" values from callbacks doesn't make sense in the context of an event driven program. Callbacks are called as the result of an event, so there's nowhere to return a value to.

As a general rule of thumb, your callbacks should always call a function, rather than using functools.partial or lambda. Those two are fine when needed, but if you're using an object-oriented style of coding they are often unnecessary, and lead to code that is more difficult to maintain than it needs to be.

For example:

def compute():
    value = var.get()
    result = square(value)
    list_of_results.append(result)

button = Tk.Button(root, text='click', command = compute)
...

This becomes much easier, and you can avoid global variables, if you create your application as a class:

class App(...):
    ...
    def compute():
        ...
        result = self.square(self.var.get())
        self.results.append(result)
Answer from Bryan Oakley on Stack Overflow
Top answer
1 of 3
11

The notion of "returning" values from callbacks doesn't make sense in the context of an event driven program. Callbacks are called as the result of an event, so there's nowhere to return a value to.

As a general rule of thumb, your callbacks should always call a function, rather than using functools.partial or lambda. Those two are fine when needed, but if you're using an object-oriented style of coding they are often unnecessary, and lead to code that is more difficult to maintain than it needs to be.

For example:

def compute():
    value = var.get()
    result = square(value)
    list_of_results.append(result)

button = Tk.Button(root, text='click', command = compute)
...

This becomes much easier, and you can avoid global variables, if you create your application as a class:

class App(...):
    ...
    def compute():
        ...
        result = self.square(self.var.get())
        self.results.append(result)
2 of 3
9

Sorry for being 6 years late, but recently I figured out a good way to do this without making your code messy and hard to maintain. This is pretty much what DaveTheScientist has said, but I just want to expand on it a little. Usually, in Tkinter, if you want to have a button call a function, you do the following:

exampleButton = Button(root, text = 'Example', command = someFunc)

This will simply call someFunc whenever the button is pressed. If this function, however, takes arguments, you need to use lambdas and do something like this:

exampleButton = Button(root, text = 'Example', command = lambda: someFunc(arg1, arg2))

The above line of code will run someFunc and use the variables arg1 and arg2 as arguments for that function. Now, what you could do in a program where, a lot of the times, you would need the functions run by buttons to return values, is create a new function which is called by every button.

This function takes the function you want your button to run as a first argument, and that function's arguments afterwards.

def buttonpress(function, *args):
    value = function(*args)

Then when you create the button, you do:

exampleButton = Button(root, text = 'Example', command = lambda: buttonpress( someFunc, arg1, arg2 ))

This will run the given function (in this case, someFunc) and store the returned value in the value variable. It also has the advantage that you can use as many arguments as you want for the function your button runs.

🌐
Python Forum
python-forum.io › thread-12007.html
Unable to return value from callback function of a button in Python Tkinter
Hi Team I am trying to get the input written in an Entry box using Tkinter, But whenever I am trying to do so I am not getting the desired result..Instead a None is getting returned. Please help My code is given below from Tkinter import * class me...
🌐
Reddit
reddit.com › r/python › using tkinter after and get a return value
r/Python on Reddit: Using Tkinter After And Get A Return Value
November 28, 2019 -

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()
🌐
Reddit
reddit.com › r/learnpython › how to return variables from tkinter windows?
r/learnpython on Reddit: How to return variables from Tkinter windows?
January 7, 2024 -

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 error

but 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?

Top answer
1 of 4
4
Method 1: use an instance variable in the toplevel class. Requires that the popup is "modal" (disables the main window). import tkinter as tk class Main(tk.Frame): def __init__(self, master=None, **kwargs): super().__init__(master, **kwargs) lbl = tk.Label(self, text="this is the main frame\n") lbl.pack() btn = tk.Button(self, text='click me', command=self.open_popup) btn.pack() self.output = tk.Label(self) self.output.pack() def open_popup(self): print("runs before the popup") p = Popup(self) print("runs after the popup closes") self.output.config(text=f"Got data returned:\n {p.result!r}") class Popup(tk.Toplevel): """modal window requires a master""" def __init__(self, master, **kwargs): super().__init__(master, **kwargs) lbl = tk.Label(self, text="this is the modal window popup\ntype something") lbl.pack() self.ent = tk.Entry(self) self.ent.insert(0, "Hello world") self.ent.pack() btn = tk.Button(self, text="OK", command=self.on_ok) btn.pack() # The following commands keep the popup on top. # Remove these if you want a program with 2 responding windows. # These commands must be at the end of __init__ self.transient(master) # set to be on top of the main window self.grab_set() # hijack all commands from the master (clicks on the main window are ignored) master.wait_window(self) # pause anything on the main window until this one closes def on_ok(self): self.result = self.ent.get() # save the return value to an instance variable. self.destroy() def main(): root = tk.Tk() window = Main(root) window.pack() root.mainloop() if __name__ == '__main__': main() Method 2: Send a callback from the main code to the toplevel window: import tkinter as tk class Main(tk.Frame): def __init__(self, master=None, **kwargs): super().__init__(master, **kwargs) lbl = tk.Label(self, text="this is the main frame\n") lbl.pack() btn = tk.Button(self, text='click me', command=self.open_popup) btn.pack() self.output = tk.Label(self) self.output.pack() def open_popup(self): Popup(self, self.update_main) # send the method that should be called at the end def update_main(self, result): self.output.config(text=f"Got data returned:\n {result!r}") class Popup(tk.Toplevel): def __init__(self, master, callback, **kwargs): super().__init__(master, **kwargs) self.callback = callback lbl = tk.Label(self, text="this is the modal window popup\ntype something") lbl.pack() self.ent = tk.Entry(self) self.ent.insert(0, "Hello world") self.ent.pack() btn = tk.Button(self, text="OK", command=self.on_ok) btn.pack() def on_ok(self): self.callback(self.ent.get()) # send the back to the other class. self.destroy() def main(): root = tk.Tk() window = Main(root) window.pack() root.mainloop() if __name__ == '__main__': main() Method 3: pass along a tkinter variable and just have all places that need it linked. Immediate updates if used as a textvariable. import tkinter as tk class Main(tk.Frame): def __init__(self, master=None, **kwargs): super().__init__(master, **kwargs) lbl = tk.Label(self, text="this is the main frame\n") lbl.pack() btn = tk.Button(self, text='click me', command=self.open_popup) btn.pack() self.txtvar = tk.StringVar(value="Hello World") self.output = tk.Label(self, textvariable=self.txtvar) self.output.pack() def open_popup(self): Popup(self, self.txtvar) class Popup(tk.Toplevel): def __init__(self, master, txtvar, **kwargs): super().__init__(master, **kwargs) lbl = tk.Label(self, text="this is the modal window popup\ntype something") lbl.pack() self.ent = tk.Entry(self, textvariable=txtvar) # could also use txtvar.set() in the ok method. self.ent.pack() btn = tk.Button(self, text="OK", command=self.destroy) btn.pack() def main(): root = tk.Tk() window = Main(root) window.pack() root.mainloop() if __name__ == '__main__': main() Method 4: use a tkinter Event to signal when things should happen. I used a global data structure here but you could also pass a mutable around instead. import tkinter as tk data_structure = "" # any kind of data structure class Main(tk.Frame): def __init__(self, master=None, **kwargs): super().__init__(master, **kwargs) lbl = tk.Label(self, text="this is the main frame\n") lbl.pack() btn = tk.Button(self, text='click me', command=self.open_popup) btn.pack() self.output = tk.Label(self) self.output.pack() master.bind("<>", self.update_main) def open_popup(self): Popup(self, self.update_main) def update_main(self, event=None): self.output.config(text=f"Got data returned:\n {data_structure!r}") class Popup(tk.Toplevel): def __init__(self, master, callback, **kwargs): super().__init__(master, **kwargs) self.callback = callback lbl = tk.Label(self, text="this is the modal window popup\ntype something") lbl.pack() self.ent = tk.Entry(self) self.ent.insert(0, "Hello world") self.ent.pack() btn = tk.Button(self, text="OK", command=self.on_ok) btn.pack() def on_ok(self): global data_structure data_structure = self.ent.get() # save the data. self.master.event_generate("<>") # trigger actions elsewhere self.destroy() def main(): root = tk.Tk() window = Main(root) window.pack() root.mainloop() if __name__ == '__main__': main() method 5: Similar to event based, use a loop to wait for new data. Allows new data to come from many places. Again could use global data structure, but for contrast will use mutable instance variable: import tkinter as tk from queue import Queue class Main(tk.Frame): def __init__(self, master=None, **kwargs): super().__init__(master, **kwargs) self.data_structure = Queue() lbl = tk.Label(self, text="this is the main frame\n") lbl.pack() btn = tk.Button(self, text='click me', command=self.open_popup) btn.pack() self.output = tk.Label(self) self.output.pack() self.event_monitor() # start the loop to monitor for new data def open_popup(self): Popup(self) def event_monitor(self): if not self.data_structure.empty(): result = self.data_structure.get() self.output.config(text=f"Got data returned:\n {result!r}") self.after(100, self.event_monitor) class Popup(tk.Toplevel): """modal window requires a master""" def __init__(self, master, **kwargs): super().__init__(master, **kwargs) lbl = tk.Label(self, text="this is the modal window popup\ntype something") lbl.pack() self.ent = tk.Entry(self) self.ent.insert(0, "Hello world") self.ent.pack() btn = tk.Button(self, text="OK", command=self.on_ok) btn.pack() def on_ok(self): self.master.data_structure.put(self.ent.get()) # send the data to the queue self.destroy() def main(): root = tk.Tk() window = Main(root) window.pack() root.mainloop() if __name__ == '__main__': main() Method 6: trace a variable: import tkinter as tk class Main(tk.Frame): def __init__(self, master=None, **kwargs): super().__init__(master, **kwargs) lbl = tk.Label(self, text="this is the main frame\n") lbl.pack() btn = tk.Button(self, text='click me', command=self.open_popup) btn.pack() self.txtvar = tk.StringVar(value="Hello World") self.txtvar.trace_add("write", self.update_main) self.output = tk.Label(self) self.output.pack() def open_popup(self): print("runs before the popup") Popup(self, self.txtvar) print("runs after the popup closes") def update_main(self, *event): self.output.config(text=f"Got data returned:\n {self.txtvar.get()!r}") class Popup(tk.Toplevel): def __init__(self, master, txtvar, **kwargs): super().__init__(master, **kwargs) lbl = tk.Label(self, text="this is the modal window popup\ntype something") lbl.pack() self.ent = tk.Entry(self, textvariable=txtvar) # or use txtvar.set() from the ok button callback self.ent.pack() btn = tk.Button(self, text="OK", command=self.destroy) btn.pack() def main(): root = tk.Tk() window = Main(root) window.pack() root.mainloop() if __name__ == '__main__': main() etc, etc. Many ways to do this.
2 of 4
2
In short, classes. Busy now, but I can give an example later.
🌐
Quora
quora.com › How-can-you-return-a-value-from-a-function-that-is-executed-from-the-Tkinter-button-Python-TkInter-development
How to return a value from a function that is executed from the Tkinter button (Python, TkInter, development) - Quora
Most commonly, what you want to do is to have a StringVar/IntVar/BoolVar member of your class, and store your value by calling its set method. (That member might be directly connected to a widget by Tk, or it might be something you manually call get on elsewhere in your code.) Something like this: ... How do you run Tkinter function with both a key bind and a button command (Python, function, tkinter, development)? How do you update label text in Python Tkinter (Python, TkInter, development)? RelatedHow do you return a function in Python (Python, return, development)?
🌐
YouTube
youtube.com › watch
tkinter variables and tkinter callback functions - YouTube
AboutPressCopyrightContact usCreatorsAdvertiseDevelopersTermsPrivacyPolicy & SafetyHow YouTube worksTest new featuresNFL Sunday Ticket · © 2025 Google LLC
Published   January 16, 2021
🌐
Python.org
discuss.python.org › python help
Tkinter dialog and getting result back to calling function - Python Help - Discussions on Python.org
May 27, 2020 - I’ve written a generic function that puts up a dialog with an Entry widget. I am successful in getting the response but now I don’t know how to return that response to the calling method. Here is the dialog function: def dialog(master,txt,default): window=Toplevel() window.resizable(False,False) string=StringVar() string.set(default) textLabel=Label(window,text=txt) textLabel.grid(row=0,column=0) textBox=Entry(window,textvariable=string) textBox.grid(row=0,column...
Find elsewhere
🌐
Python Tutorial
pythontutorial.net › home › tkinter tutorial › tkinter command binding
Tkinter Command Binding - Python Tutorial
April 3, 2025 - In this tutorial, you'll learn about the Tkinter command binding that associates a callback with an event of a widget.
🌐
Stack Overflow
stackoverflow.com › questions › 68232494 › lambda-tkinter-not-able-to-return-value-from-button-callback
lambda tkinter not. able to return value from button callback - Stack Overflow
Instead of returning value from function, make the variable clk or CLOCK (whichever you are updating) as global, and then in function change_direction_dummy() you can set the value of the global variable ...
🌐
MetaFilter
ask.metafilter.com › 183748 › PythonTkinter-data-passing
Python-Tkinter data passing - GUI programming | Ask MetaFilter
April 18, 2011 - I know I could use global variables, but there has to be a better way right..something like a return statement? posted by anaelith at 1:54 PM on April 18, 2011 · Actually, that code is already set up to run the callback() method whenever the button is clicked. So you can just implement that method to do what you want. Here's how to make it increment your counter variable: def callback(self): global counter counter += 1 Three things to note: Tkinter is widely considered obsolete; it might be better to go with a modern library like PyQt.
Top answer
1 of 3
1

You could first display the combobox DataChosenForm(self).grid(row=0, column=0) without calling the ReturnData in the Application class.

Then, in the callback() method collect the choice choice = event.widget.get() and pass it to ReturnData. This would mean, however, that the LabelFrame is displayed only after a choice is made.

import tkinter as tk
from tkinter import ttk

class DataChosenForm(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        chosen = tk.LabelFrame(self, text="wybór")
        chosen.grid(row=0)
        self.combo = ttk.Combobox(chosen)
        self.combo['values'] = ('wizz', 'ryanair', 'lot')
        self.combo.grid(row=0, column=2, padx=80, pady=10)
        self.combo.bind("<<ComboboxSelected>>", self.callback)

    def callback(self, event=None):
        choice = event.widget.get()
        print(choice)
        ReturnData(self, choice).grid(row=1)

class ReturnData(tk.Frame):
    def __init__(self, parent, choice):
        super().__init__(parent)
        message_box = tk.LabelFrame(self, text="wynik")
        message_box.grid(row=1)
        mb = tk.Label(message_box, text=choice, anchor='nw')
        mb.pack(padx=120, pady=30)

class Application(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("program do wyszukiwania cen lotów")
        self.geometry('300x200')
        self.resizable(width=False, height=False)
        DataChosenForm(self).grid(row=0, column=0)

if __name__ == "__main__":
    app = Application()
    app.mainloop()
2 of 3
0

I think @Julia has the basically the right architecture for your tkinter application, but her answer could be improved by using a tkinter Variable — because all widgets associated with one will automatically update their displayed value whenever the Variable is changed (by one of them or something else).

Here's a little documentation on Variable Classes. Note that since ttk.Combobox with have all the methods of a tk.Entry widgets, here's a bit of documentation about them (which also happens to illustrate the "pattern" of using of a StringVar in conjunction with one so it also applies to a ttk.Comboboxs).

Generally, you can tell a widget to use a tkinter Variable by specifying an instance of one as the option textvariable= keyword argument when the widget is created. You can also set the option using the partial dictionary interface most widgets support, so assignments like widget['textvariable'] = variable are another way to make use of them — the code below makes use of both of these ways.

Here's Julia's code modified to use a tk.StringVar. Note the Combobox doesn't need a callback function to bind the <<ComboboxSelected>> event to it, so all that complexity has been eliminated.

import tkinter as tk
from tkinter import ttk

class DataChosenForm(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        choice = tk.LabelFrame(self, text="wybór")
        choice.grid(row=0)
        self.combo = ttk.Combobox(choice)
        self.combo['textvariable'] = parent.var  # Use shared variable.
        self.combo['values'] = ('wizzair', 'ryanair', 'lot')
        self.combo.grid(row=0, column=2, padx=80, pady=10)

class ReturnData(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        message_box = tk.LabelFrame(self, text="wynik")
        message_box.grid(row=1)
        mb = tk.Label(message_box, textvariable=parent.var,  # Use shared variable.
                      anchor='nw', width=20)
        mb.pack(padx=120, pady=30)

class Application(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("program do wyszukiwania cen lotów")
        self.geometry('300x200')
        self.resizable(width=False, height=False)
        self.var = tk.StringVar(value='Dokonać wyboru')  # Create shared variable.

        DataChosenForm(self).grid(row=0, column=0)
        ReturnData(self).grid(row=1)

if __name__ == "__main__":
    app = Application()
    app.mainloop()
🌐
Quora
quora.com › How-can-I-define-a-sequence-of-callback-functions-in-Python-Tkinter
How to define a sequence of callback functions in Python Tkinter - Quora
Answer: You can create your buttons inside a loop, just like any other time you want to do a series of operations that differ by some sequentially computable parameter(s). Button callback functions in TkInter have no parameters because they are going to be called from the Button event generating...
🌐
TutorialsPoint
tutorialspoint.com › how-can-i-pass-arguments-to-tkinter-button-s-callback-command
How can I pass arguments to Tkinter button's callback command?
In this example, we will create a simple application that will contain a text label and a button to change the value of label text. We will pass the label as the argument in the button command by using lambda function. #Import necessary Library from tkinter import * from tkinter import ttk #Create an instance of tkinter window win= Tk() #Set the geometry of tkinter window win.geometry("750x250") #Define the function to change the value in label widget def change_text(label): label.configure(text= "Hey, I am Label-2", background="gray91") #Create a Label label = Label(win, text= "Hey, I am Label-1", font= ('Helvetica 15 underline'), background="gray76") label.pack(pady=20) #Create a button btn= ttk.Button(win, text= "Change", command= lambda:change_text(label)) btn.pack(pady=10) win.mainloop()
🌐
Stack Overflow
stackoverflow.com › questions › 44578683 › tkinter-get-return-value-from-a-callback-using-a-class-method
python - Tkinter: Get return value from a callback using a class method? - Stack Overflow
You can't return anything to the main function—it didn't call result.setdir(), dirbrowse.mainloop() did. After the button is selected and setdir() is called, it will be stored in result.path. You either need to make setdir() do more, or periodically check the value of result.path.
🌐
Google APIs
storage.googleapis.com › dbalarwbwgfxme › tkinter-button-command-with-return-value.html
Tkinter Button Command With Return Value at Nathan Fulton blog
July 23, 2024 - First, you need to make your variable of a tkinter string type like this: ... The only known way to get the return value of a button command is by using button.invoke(). The entry widget has a get() method to get the value entered by the user. When you click or press the button, it’ll automatically invoke a callback function.
🌐
Code Redirect
coderedirect.com › questions › 418551 › returning-a-value-after-calling-a-function-with-a-button-in-tkinter
[Solved] Python Returning a value after calling a function with a button in Tkinter - Code Redirect
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.