Search code examples
pythontkinteruser-input

Python Tkinter: Function to return user input once a button is clicked


I'm writing a small program in python that consists of a backend that processes some data, and a frontend using tkinter. To process the data, the backend may sometimes need userinput. My idea was to call the backend data processing function from the frontend, giving it as input a function from the frontend that opens a pop-up window asking for input and returns it once the user clicks a "Submit" button. However, I'm having trouble returning only once the button is clicked. The following is a dummy example of what I've tried.

import tkinter as tk

def backend_function(func):
    #some data processing function
    user_input = func()
    print(user_input)
    
def pop_up(master):
    #opens pop-up window asking for inout and return the input once "submit" is clicked
    top = tk.Toplevel(master=master)
    entry = tk.Entry(top)
    entry.pack()
    
    submit = tk.Button(top, text='Submit', command = None)
    submit.pack()
    
    return entry.get() #should return only on click...
    

root = tk.Tk()

#start data processing from interface
call_backend = tk.Button(root, text = 'Backend',
                         command = lambda: backend_function(lambda: pop_up(master=root)))
call_backend.pack()

root.mainloop()

The problem is, that I'd like to have the return statement of pop_up as a command of the button, which is not possible. I thought about setting a nested function as command of the button, but then again, the nested function can't give a return value of the original function either.

Is it even possible to solve the problem this way, or would I have to delve deeper into tkinter defining some new Toplevel class or what not? Still fairly new to tkinter. Thanks!


Solution

  • You can use top.wait_window() to wait for the closing of the toplevel window and then get the input value via a StringVar associated with entry:

    def pop_up(master):
        #opens pop-up window asking for inout and return the input once "submit" is clicked
        top = tk.Toplevel(master=master)
    
        my_var = tk.StringVar() # used to return the input value
        entry = tk.Entry(top, textvariable=my_var)
        entry.pack()
    
        submit = tk.Button(top, text='Submit', command=top.destroy) # close top when clicked
        submit.pack()
    
        top.grab_set() # grab the input focus
        top.wait_window() # wait for the window close
    
        # use my_var.get() instead of entry.get() because entry is destroyed
        return my_var.get() #should return only on click...
    

    If you just want to open a dialog to input something, simply use simpledialog.askstring():

    ...
    from tkinter.simpledialog import askstring
    ...
    def pop_up(master):
        return askstring(title="Input", prompt="Enter something", parent=master)