I have defined the following functions in a module called script.py
def load_file():
file_name = filedialog.askopenfile(filetypes=['EXE files', '*.exe'])
return file_name
def simulation(input_path, input_par): # this works fine
# the functionruns an EXE file ang gives me two lists lst1 and lst2
return lst1, lst2
Now the following button defined in the main.py
calls the load_file
function and it works fine (I print the path from within the function in the terminal). What I cannot figure out is how to pass the path I get within the load_file
function as argument input_path
to the function simulation via the button within the main.py
.
input_var = #??
button = Button(frame_file, text='Open file', command=load_file)
button.grid(row=1, column=1)
simulation(input_path, input_var)
CodePudding user response:
You could use the partial
method to pass parameters.
simulation = partial(simulation, input_path, input_par)
buttonCal = tk.Button(root, text="Simulate", command=simulation)
CodePudding user response:
I think your question is a duplicate, it's just not apparent from the title, because it is worded a bit weirdly:
How to return value from tkinter button callback
I can propose a solution other than what's in the thread, but it's admittedly not clean.
You can use a lambda, or the already mentioned partial
method to pass a mutable object, as described by @vnk. Using lambdas (or partially applied functions) is the usual way to pass arguments to Tkinter callbacks.
Since I assume that your path is probably a string, which is immutable, you should either use an object such as a pathlike.Path, or create an object yourself and wrap your path string into it. Unfortunately, your callback has to cooperate for this as well.
path_container = [] # You could define a class to have cleaner code than having to use the magic 0 index.
tk.Button(root, text="Open file", command=(lambda: load_file(path_container)))
# Your load_file has to know that its argument is a list whose 0-th element must contain the path,
# or, if you opt for the more readable approach, that the .path attribute of your
# path container object should be used.
If you go really wild, you can even create a function just to change a mutable object, so you don't have to change your load_file
function:
def store_path(path_container, path):
path_container[0] = path # Or path_container.path = path, if you're doing it cleaner.
tk.Button(root, text="Open file", command=(lambda: store_path(path_container, load_file())))
A lambda is useful because it captures variables from the parent scope, such as path_container
.
A helper is needed because of the limitation applying to lambdas that their body must be a single expression, which an assignment (in reality, name binding) is not, in Python. It is in many other languages, such as C.
Honestly, the most sensible solution is probably to design your callback to use a pathlib.Path object. If your program grows large, you will benefit from having a proper path class instead of a string anyway, even if you don't use Tkinter.