I'm writing a client-server program in Python with Tkinter. I need the server to keep track of the connected clients. For this, I would like to have the client send an automated message to the server after the exit button(the standard "X" in the corner) is clicked. How can I know when the user is exiting the program?
You want to use the wm_protocol method of the toplevel window. Specifically, you are interested in the WM_DELETE_WINDOW
protocol. If you use that method, it allows you to register a callback which is called when the window is being destroyed.
Usage:
root.protocol("WM_DELETE_WINDOW", app.on_delete)
root.protocol("WM_DELETE_WINDOW", app.on_delete())
right before my call to root.mainloop()
but on_delete()
is getting called when the window is opened and not when it is closed. Am I doing something wrong? –
Disjunction protocol
method takes a reference to a function. By adding the trailing parenthesis you are calling app.on_delete
and passing the result of that method to the protocol handler. The correct usage is root.protocol("WM_DELETE_WINDOW", app.on_delete)
–
Lightheaded Frame
subclass whose command=self.quit
). That said, it does answer this question which asks only about the standard exit button. –
Fascine quit
, you're just instructing mainloop
to exit, and the window is destroyed gracefully. –
Lightheaded You can use python atexit
module.
For example:
import atexit
def doSomethingOnExit():
pass
atexit.register(doSomethingOnExit)
In my case, the following code didn't work:
root.protocol("WM_DELETE_WINDOW", app.on_delete) # doesn't work
However, it worked using this form:
root.wm_protocol ("WM_DELETE_WINDOW", app.on_delete) # does work
.protocol
, though... the accepted answer already said to use .wm_protocol
. –
Laggard .protocol
, not .wm_protocol
. In any case, both options behave in the exact same way on my machine, I assume piertoni's version differs from mine (unsurprisingly so since the answer dates back to 2012). –
Currin protocol
and wm_protocol
are exactly the same function. –
Lightheaded FWIW: It is also possible to assign a widget-specific behavior.
If you want an action to occur when a specific widget is destroyed, you may consider overriding the destroy() method. See the following example:
class MyButton(Tkinter.Button):
def destroy(self):
print "Yo!"
Tkinter.Button.destroy(self)
root = Tkinter.Tk()
f = Tkinter.Frame(root)
b1 = MyButton(f, text="Do nothing")
b1.pack()
f.pack()
b2 = Tkinter.Button(root, text="f.destroy", command=f.destroy)
b2.pack()
root.mainloop()
When the button 'b2' is pressed, the frame 'f' is destroyed, with the child 'b1' and "Yo!" is printed.
I posted the same answer on this topic.
Don't forget to use a lambda like this:
class App:
def run(self):
self.root.protocol("WM_DELETE_WINDOW", lambda: self.quit())
def quit(self):
self.root.destroy()
© 2022 - 2024 — McMap. All rights reserved.