2

Currently learning tkinter and have come to a dead end. Each time I click one of the buttons in my GUI (after typing 'username' and 'password' into the log in screen) a new child window is created and appears. As it should. What I would now like to do is to ensure that only one window is created and any subsequent clicks do not create yet more windows. How could this be done?

from tkinter import *

class Main():

    def __init__(self, master):
        self.master = master
        self.master.title("Main Window")

        self.button1 = Button(self.master, text="Click Me 1", command = self.Open1)
        self.button1.grid(row=0, column=0, sticky=W)
        self.button2 = Button(self.master, text="Click Me 2", command = self.Open2)
        self.button2.grid(row=0, column=2, sticky=W)
        self.button3 = Button(self.master, text="Close", command = self.Close)
        self.button3.grid(row=1, column=0, sticky=W)

    def Login(self):

        login_win = Toplevel(self.master)
        login_window = Login(login_win)
        login_window.Focus()
        #main_window.Hide()


    def Open1(self):
        second_window = Toplevel(self.master)
        window2 = Second(second_window)

    def Open2(self):
        third_window = Toplevel(self.master)
        window3 = Third(third_window)

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

    #def Hide(self):
        #self.master.withdraw()

    #def Appear(self):
        #self.master.deiconify()


class Second():

    def __init__(self, master):
        self.master = master
        self.master.title("Child 1 of Main")
        self.master.geometry("300x300")
        self.button4 = Button(self.master, text="Click Me 1", command = self.Open_Child)
        self.button4.grid(row=0, column=0, sticky=W)


    def Open_Child(self):
        second_child_window = Toplevel(self.master)
        window4 = Second_Child(second_child_window)

class Third():
    def __init__(self, master):
        self.master = master
        self.master.geometry("300x300")
        self.master.title("Child 2 of Main")

class Second_Child():
    def __init__(self, master):
        self.master = master
        self.master.geometry("400x300")
        self.master.title("Child of 'Child 1 of Main'")

class Login():
    def __init__(self, window):

        self.window = window
        self.window.title("Current Library")

        Label(self.window, text="Log in to use this program:").grid(row=0, column=0, sticky=W)

        self.userbox=Entry(self.window, width=20, bg="light green")
        self.userbox.grid(row=1, column=0, sticky=W)

        self.passbox=Entry(self.window, width=20, bg="light green")
        self.passbox.grid(row=2, column=0, sticky=W)

        Button(self.window, text="Submit", width=5, command=self.clicked).grid(row=3, column=0, sticky=W)

    def Focus(self):
        self.window.attributes('-topmost', 1)
        self.window.grab_set()

    def clicked(self):
        username = self.userbox.get()
        password = self.passbox.get()
        if password == "password" and username == "username":
            self.correct = True
            self.window.grab_release()
            self.window.destroy()
        else:
            pass

root_window = Tk()
root_window.iconbitmap(default='transparent.ico')
root_window.geometry("200x100")

main_window = Main(root_window)
main_window.Login()

root_window.mainloop()

Inside the functions which are called when the buttons are clicked could I add an IF statement?: IF window object does not exist then instantiate window object ELSE pass.

def Open1(self):
    if window2 == False:
        second_window = Toplevel(self.master)
        window2 = Second(second_window)
    else:
        pass

If this is the correct logic then how can I check if a window object has already been created because the above doesn't work as I am referencing the object before it is created?

Many thanks.

sw123456
  • 3,339
  • 1
  • 24
  • 42

1 Answers1

5

Initialize the child window variable in Main's __init__.

self.child_window = None

Then you can check whether it exists in Open1.

def Open1(self):
    if not self.child_window:
        self.child_window = Second(Toplevel(self.master))

By the way, if you intend for Second to act like its own window, it's a bit awkward that you have to create a Toplevel every time you want to create a Second. Conventionally, you would make Second a subclass of Toplevel, so it can be created on its own. Something like:

class Second(Toplevel):
    def __init__(self, master, *args, **kargs):
        Toplevel.__init__(self, master, *args, **kargs)
        #rest of initialization goes here. 
        #Use `self` everywhere you previously used `self.master`.

Now you could just do:

def Open1(self):
    if not self.child_window:
        self.child_window = Second(self.master)
Kevin
  • 74,910
  • 12
  • 133
  • 166
  • Another related question: How could I then reassign 'None' into variable 'self.child_window' when the child window is closed (exited with red cross)? – sw123456 Jul 22 '14 at 14:22
  • You can register a callback function that gets called when the window is closed. See [this post](http://stackoverflow.com/questions/3295270/python-tkinter-x-button-control-the-button-that-close-the-window) for more information. – Kevin Jul 22 '14 at 14:50