Search code examples
pythontkinterfiledialog

Conflict between two tkinter GUI's Variable


I have one main GUI and secondary GUI, the secondary GUI can be called independently and also by pressing a button on the main GUI.

Scenario1: When I directly open the secondary GUI everything works.

Scenario2: When I call secondary GUI from Main GUI. There is some conflict between the variables of the two GUIs. I have created one highly simplified example and it is also producing the same issue.

Problem: After opening Secondary GUI from Main GUI, when we try to select a path from 2nd GUI, it simply does not appear in the entry widget. However, it sets the value in the variable and can be printed.

I am looking for a solution that helps me keep both the files separately(I don't want to merge the secondary GUI in MainGUI)

I know, it is some silly mistake I am making, but any help would be appreciated.

Main_GUI.py

import tkinter as tk
from tkinter import filedialog
import os
#from b import *

class App:
    def __init__(self, master):
        self.master = master
        master.geometry('470x100')
        master.title("Main GUI")

        # Path
        self.labelframe0 = tk.LabelFrame(master, text="Enter path",width=10,height=55, font=("TkDefaultFont", 9, "bold"))
        self.labelframe0.pack(fill="both", expand="yes")
        self.folder_path = tk.StringVar()
        self.lbl1 = tk.Entry(self.labelframe0, textvariable=self.folder_path, width=67)
        self.lbl1.place(x=0, y=4)
        self.button2 = tk.Button(self.labelframe0, text="Browse", bg="orange", fg="black", command=self.browse_button)
        self.button2.place(x=410, y=0)

        # Button
        self.labelframe1 = tk.LabelFrame(master, text="Button",width=10,height=50, font=("TkDefaultFont", 9, "bold"))
        self.labelframe1.pack(fill="both", expand="yes")
        self.btn2 = tk.Button(self.labelframe1, text="Secondary GUI", bg="orange", fg="black", command=self.SecondaryGUI)
        self.btn2.place(x=0, y=0)


    def SecondaryGUI(self): 
        with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "b.py"), "r") as source_file:
            code = compile(source_file.read(), os.path.join(os.path.dirname(os.path.abspath(__file__)), "b.py"), "exec")
        exec(code, {})
        #b()

    def browse_button(self):
        self.folder_path.__del__
        filename = filedialog.askdirectory()
        self.folder_path.set(filename)
        print(self.folder_path.get())
        

def main():
    window = tk.Tk()
    root = App(window)
    window.mainloop()

if __name__ == '__main__':
    main()

Secondary.py

import tkinter as tk
from tkinter import filedialog
import os

class a_app:
    def __init__(self, window):
        self.window = window
        self.window.geometry('400x60')
        self.window.title("Secondary GUI")

        # path
        self.labelframe0 = tk.LabelFrame(self.window, text="Path to save",width=10,height=55, font=("TkDefaultFont", 9, "bold"))
        self.labelframe0.pack(fill="both", expand="yes")
        self.folder_path = tk.StringVar()
        self.lbl1 = tk.Entry(self.labelframe0, textvariable=self.folder_path, width=53)
        self.lbl1.place(x=0, y=4)
        self.button2 = tk.Button(self.labelframe0, text="Browse", bg="orange", fg="black", command=self.browse_button)
        self.button2.place(x=325, y=0)

    def browse_button(self):
        self.folder_path.__del__
        self.filename = filedialog.askdirectory(parent=self.window)
        self.folder_path.set(self.filename)
        print(self.folder_path.get())

inst = tk.Tk()
root = a_app(inst)
inst.mainloop()

Manish


Solution

  • Each time you create a new instance of Tk() a new Tcl interpreter is created. Each interpreter is like an isolated sandbox with its own memory. Therefore, widgets and variables created in one Tcl interpreter can't be accessed from other interpreters .

    When you used tk.StringVar() without passing the master keyword argument, tkinter had to guess which interpreter to use. It always picks the first instance of Tk() that was created. That is why you had problems.

    That is why people usually recommend using tk.Tk() only once and using tk.Toplevel(), if you need more windows.