Python tkinter:如何确保每次点击按钮只创建一个子窗口,而不是每次都新建窗口?

2 投票
1 回答
3406 浏览
提问于 2025-04-18 14:15

我现在正在学习tkinter,但遇到了一些问题。每次我在登录界面输入“用户名”和“密码”后点击按钮,就会出现一个新的子窗口,这本来是正常的。但我现在想要确保只创建一个窗口,后续的点击不会再创建更多的窗口。我该怎么做呢?

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()

在按钮点击时调用的函数里,我可以加一个IF语句吗?比如:如果窗口对象不存在,就创建一个窗口对象;否则就不做任何事情。

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

如果这个逻辑是对的,那我该怎么检查一个窗口对象是否已经被创建呢?因为上面的做法在我创建对象之前就引用了它,所以不太管用。

非常感谢。

1 个回答

5

在主窗口的 __init__ 方法里初始化子窗口的变量。

self.child_window = None

然后你可以在 Open1 方法里检查这个子窗口是否存在。

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

顺便说一下,如果你希望 Second 窗口能像独立的窗口一样工作,那么每次想要创建 Second 窗口时都要创建一个 Toplevel 确实有点麻烦。通常情况下,你会把 Second 设为 Toplevel 的子类,这样它就可以独立创建了。像这样:

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`.

现在你可以直接这样做:

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

撰写回答