2

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

Manish
  • 27
  • 3

1 Answers1

1

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.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
TheLizzard
  • 7,248
  • 2
  • 11
  • 31
  • _"Each interpreter is its own process with its own memory."_ - that is not correct. All tcl interpreters run in the same process unless you explicitly create a new process for them. – Bryan Oakley May 02 '21 at 18:59
  • @BryanOakley Oh, I didn't know that. Do they run in separate threads? I will update my answer. – TheLizzard May 02 '21 at 19:12
  • No, not separate threads either. They all run in the same thread, in the same process. – Bryan Oakley May 02 '21 at 19:12
  • @BryanOakley That would explain why `.mainloop(n=0)` is able to run even if its master root is dead. It waits until all of the windows are closed even if they aren't part of the main root. – TheLizzard May 02 '21 at 19:15
  • _"each interpreter isn't own process but it acts that way."_ - I don't think that's true either. Separate processes are completely isolated. The tcl interpreters aren't. For example, all tcl interpreters have access to the same process environment variables, they all run in the same python thread, they can all share a single invocation of `mainloop`. While there are similarities, it's a bit of a stretch to say they act like processes. I think saying so might be confusing. – Bryan Oakley May 02 '21 at 19:19
  • @BryanOakley Well I don't know how to phrase it properly. Do you mind editing my answer please? – TheLizzard May 02 '21 at 19:22
  • @BryanOakley Thx really appreciate it – TheLizzard May 02 '21 at 20:22