'How do I close a Tkinter window and retain a StringVar value?

I am having a couple issues with the following code:

  1. After the radio button is selected and the OK button is selected, the Tkinter window does not close. I have tried various methods to close the Tkinter window - quit() and destroy() both inside buttonAction() and after master.mainloop() - but neither has worked. The code will run endlessly and the window does not close.
  2. The compGDB variable assignment is not retained after the code is run. At this point, I'm wondering if the compGDB variable isn't retaining simply because the destroy/quit code failure.

import Tkinter, getpass
username = getpass.getuser()

def buttonAction():
    compGDB = choice.get()
    print compGDB
    #master.quit()
    #master.destroy()

vwrMinGDB = "C:\\Users\\" + username + "\\Desktop\\ViewerAttribution\\Viewer_minimum.gdb"
fullGDB = "C:\\Users\\" + username + "\\Desktop\\ViewerAttribution\\Full_geodatabase.gdb"

master = Tkinter.Tk()
master.title("Schema comparison")
master.geometry("250x100")

choice = Tkinter.StringVar()
choice.set(vwrMinGDB)

chooseOption = Tkinter.Label(master, text="Slect geodatabase for schema comparison")
rButton1 = Tkinter.Radiobutton(master, text="Viewer Minimum Attribution", variable=choice, value=vwrMinGDB)
rButton2 = Tkinter.Radiobutton(master, text="Full Geodatabase Attribution", variable=choice, value=fullGDB)
confirmButton = Tkinter.Button(master, text="OK", command=buttonAction)

chooseOption.grid(column="1", row="0")
rButton1.grid(column="1", row="1")
rButton2.grid(column="1", row="2")
confirmButton.grid(column="1", row="3")

master.mainloop()
#master.quit()
#master.destroy()

Thanks, y'all!



Solution 1:[1]

I cannot reproduce your first issue. You can quit() by calling master.quit() within def buttonAction():, there should be something else missing.

Your second issue though, it is because compGDB is locally created within the function buttonAction, so once the function is done the attribute ceases to be.

While the better advice is to rebuild your code as a class and define compGDB as an instance/class attribute (so you can recall it as long as the class instance is still in memory), you can see it can be a bit of work. An easy workaround (IMO not best practice) would be:

compGDB = ''

def buttonAction():
    global compGDB
    compGDB = choice.get()
    master.quit()

So that this way, the global attribute compGDB is still retained and you can recall it anywhere even after master.mainloop().

But again, consider using an OOP approach for your tkinter if you have use for the information afterwards. It'll help maintain your namespace easier especially for complex scripts.

Solution 2:[2]

For the second issue: Retain a variable after tkinter window is closed with destroy() I implemented the OOP approach r.ook suggested. I took some furhter inspiration for this approach from https://www.pythontutorial.net/tkinter/tkinter-object-oriented-window/.

In my example a filepath is retained after the window is closed, but it could be any variable.

from fileinput import filename
import tkinter as tk
from tkinter import filedialog


class tkApp(tk.Tk):
    def __init__(self):
        super().__init__()
        
        self.filename = ""

        # Config root window
        self.title('Select a file to plot.')

        # Buttons
        self.my_btn = tk.Button(self, text="Select File", command=self.open_fileselect).pack()
        self.my_btn2 = tk.Button(self, text="Quit", command=self.destroy).pack()

        self.tk.mainloop()

    def open_fileselect(self):
        self.filename = filedialog.askopenfilename(initialdir=r'C:\Users\some_dir',
                title="Select A File", filetypes=(("excel sheets", "*.xlsx"),("all files", "*.*")))
        self.myLabel= tk.Label(self, text=self.filename).pack()
        self.my_img_label= tk.Label(self,text="Test").pack()
        self.data_filepath = self.filename

# Create class instance. This will automatically run tkinter, since the mainloop call is included inside the class.
my_App = tkApp()

# Retrieve the variable from the class instance
print(my_App.filename)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 r.ook
Solution 2 TheWolf