Alfonso
Alfonso

Reputation: 713

Closing main window from toplevel window with tkinter in python

This is my first question, I am new to python and this site.

I am designing an app to interact with a database. I added a "close" button that I would like to open a new window asking "close the program?" and 2 buttons: yes and no. When you click no, the new window closes. When you click yes both windows close.

I got my code working but I am quite sure there is a better or smarter way of doing it.

To make it work I had to write "root.destroy()" in the "close_window" method but I am pretty sure there is a smarter way of getting the same result with something like "self.master.destroy()" that uses all the power of python. I show a simplified version of the code below.

Thanks in advance.

Alfonso

from tkinter import *

class Window():

    def __init__(self, main):
        self.main = main

        self.b5=Button(self.main, text="Action 1", width=12)
        self.b5.grid(row=0, column=1)

        self.b5=Button(self.main, text="Action 2", width=12)
        self.b5.grid(row=0, column=2)

        self.b6=Button(self.main, text="Close", width=12, command=self.new_window)
        self.b6.grid(row=0, column=3)

    def new_window(self):
        self.newWindow = Toplevel(self.main)
        self.app = Demo2(self.newWindow)

    def close_window(self):
        root.destroy()


class Demo2:
    def __init__(self, master):
        self.master = master
        self.frame = Frame(self.master)

        self.l1=Label(self.frame, text="Close the program?")
        self.l1.grid(row=0, column=0, columnspan=2)

        self.b1=Button(self.frame, text="Yes", command=self.yes_com)
        self.b1.grid(row=1, column=0)

        self.b1=Button(self.frame, text="No", command=self.no_com)
        self.b1.grid(row=1, column=1)

        self.frame.pack()

    def yes_com(self):
        self.master.destroy()
        Window.close_window(self)

    def no_com(self):
        self.master.destroy()


def main():
    global root
    root = Tk()
    app = Window(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Upvotes: 2

Views: 1555

Answers (2)

Novel
Novel

Reputation: 13729

Pier Paolo has the right answer, but for the sake of science, here's the direct answer to your question:

def yes_com(self):
    self.master.master.destroy() # <this class instance>.<toplevel instance>.<Tk instance>.destroy()

Or you could simply quit python:

import sys

def yes_com(self):
    sys.exit()

Upvotes: 1

Pier Paolo
Pier Paolo

Reputation: 920

You could simply use the standard dialogs provided by the messagebox module.

Specifically, it provides the askyesno dialog that takes care of the opening/closing of the new window and returns True if the user clicks Yes and False if the user clicks No. Then, you could simply use an if-statement to close the window if the user says so by simply using self.main.destroy() (without the need to declare root as global).

from tkinter import *
from tkinter import messagebox

class Window():

    def __init__(self, main):
        self.main = main

        self.b5=Button(self.main, text="Action 1", width=12)
        self.b5.grid(row=0, column=1)

        self.b5=Button(self.main, text="Action 2", width=12)
        self.b5.grid(row=0, column=2)

        self.b6=Button(self.main, text="Close", width=12, command=self.close_window)
        self.b6.grid(row=0, column=3)

    def close_window(self):
        if messagebox.askyesno('Close', 'Close the program?'):
            self.main.destroy()

def main():
    root = Tk()
    app = Window(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Notes

  1. The yes/no buttons in the standard dialog are localized, meaning that they are translated into the language used by your computer settings.
  2. If you have a look around the messagebox module, you'll see that there are other standard dialogs. IMHO in this case I would use askyescancel, which is used in the exact same way, but seems more semantic.

Upvotes: 1

Related Questions