0

I think i am missing some basic understanding for functions or tying a button to a function in python. why can't I close any window with the same function. For example in the code below I can't use

from tkinter import *

def close_window(window_x):
    window_x.destroy()

window_1= Tk()
button_1=Button(window_1,text="close",command=close_window(window_1))
button_1.pack()
window_1.mainloop()

This code below works fine and i get it. Tie the button to a function that closes the specific window. But the code above makes sense to me and i'd like to use this sort of thing, but don't know why it doestn' work. Would someone explain. Thanks!

def close_window():
    window_1.destroy()

window_1= Tk()
button_1=Button(window_1,text="close",command=close_window)
costa rica
  • 57
  • 7

1 Answers1

0

Let's have a look at your first piece of code:

from tkinter import *

def close_window(window_x):
    window_x.destroy()

window_1= Tk()
button_1=Button(window_1,text="close",command=close_window(window_1))
button_1.pack()
window_1.mainloop()

So what's the issue?

The line

button_1=Button(window_1,text="close",command=close_window(window_1))

doesn't do what you're expecting it to. command=close_window(window_1) tells Python to run your function, and assign the result of it to the command argument. This means your function is executed, closing your window, and so you can't put your button in it, which is causing your error.

In your second snippet, it works because instead of assigning the result of the function call to the argument command, you're instead passing the function itself as an argument. When you click your button, your window will now close.

If you need to pass an argument to a function, consider adding a wrapper, or use a lambda statement, as such:

button_1=Button(window_1,text="close",command=lambda: close_window(window_1))

Edit:

If you want to use a wrapper, use this:

from tkinter import *

def args(*args, **kwargs):
    def inner(func):
        def wrapper():
            return func(*args, **kwargs)
        return wrapper
    return inner

window_1= Tk()

@args(window_1)
def close_window(window_x):
    window_x.destroy()

button_1=Button(window_1,text="close",command=close_window)
button_1.pack()
window_1.mainloop()

or if you need to have different arguments each time, use this:

from tkinter import *

def args(*args, **kwargs):
    def inner(func):
        def wrapper():
            return func(*args, **kwargs)
        return wrapper
    return inner

def close_window(window_x):
    window_x.destroy()

window_1= Tk()
button_1=Button(window_1,text="close",command=args(window_1)(close_window))
button_1.pack()
window_1.mainloop()
Ed Ward
  • 2,210
  • 2
  • 8
  • 15