Python tkinter root close

Question:

As an interim to my full application, I’m closing the window with buttons at different places in the file. Now originally, it works fine: I can close the application from both location within the file. However, I’m trying to clean the code up and have a better style.

Here’s the code I have (with the better style):

from tkinter import *
from tkinter import ttk

class Location:
    def __init__(self, root):
        
        root.title("Location")
        root.geometry('400x295')  
 
        self.mainframe = ttk.Frame(root, padding="3 3 12 12")
        self.mainframe.grid(column = 0, row=0, sticky=(N, W, E, S))
        root.columnconfigure(0, weight=1)
        root.rowconfigure(0, weight=1)

        confirm_button = ttk.Button(self.mainframe, text = 'CONFIRM', command = self.make_confirmation)
        confirm_button.grid(column=0, row=0)
        
        select_button = ttk.Button(self.mainframe, text = 'Geometry', command = root.quit)
        select_button.grid(column=0, row=1)  
        
    def make_confirmation(self, *args):
        root.quit()
        

def main_app():
    root = Tk()
    Location(root)
    root.mainloop()  
  
if __name__ == "__main__":
    main_app()

The "Geometry" button will close just fine.

The "Confirm" button gives me a NameError.

Note, def make_confirmation is in class Location

Traceback (most recent call last):
  File "C:UsersUserAppDataLocalProgramsPythonPython312Libtkinter__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "c:UsersUserDocumentsPythonTutorialsQuit_wStyle.py", line 22, in make_confirmation
    root.quit()
    ^^^^
NameError: name 'root' is not defined

In my non-MWE, make.confirmation does a bit more and has arguments passed through. That all works fine. I know that because when I get rid of def main_app(): and put it all in if __name__ == "__main__":, then both root.quit works.

In other words, this works:

from tkinter import *
from tkinter import ttk

class Location:
    def __init__(self, root):
        
        root.title("Location")
        root.geometry('400x295')  
 
        self.mainframe = ttk.Frame(root, padding="3 3 12 12")
        self.mainframe.grid(column = 0, row=0, sticky=(N, W, E, S))
        root.columnconfigure(0, weight=1)
        root.rowconfigure(0, weight=1)

        confirm_button = ttk.Button(self.mainframe, text = 'CONFIRM', command = self.make_confirmation)
        confirm_button.grid(column=0, row=0)
        
        select_button = ttk.Button(self.mainframe, text = 'Geometry', command = root.quit)
        select_button.grid(column=0, row=1)  
        
    def make_confirmation(self, *args):
        root.quit()
  
if __name__ == "__main__":
    main_app()
    root = Tk()
    Location(root)
    root.mainloop()  

Why is command = root.quit working?

But command = self.make_confirmation does work?

Asked By: David Collins

||

Answers:

Your root variable is scoped only for init function. If you want it to be available for the whole class, put self.root = root inside the init function. And refer to it as such in other functions of your class. if __name__ == "__main__": works because root variable is scoped to the whole file so you can get it everywhere in any function, but when you define it inside a function it is scoped to that function only, ergo variable cannot be accessed from anywhere else (you can fix it by adding global root)

Answered By: Gleb
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.