CustomTkinter创建窗口时额外生成空白tk窗口的问题求助
解决CustomTkinter中额外生成空白"tk"窗口的问题
问题描述
使用CustomTkinter开发Python GUI程序时,创建新窗口(对应代码第87行的Create_main_window函数)后,程序除了生成预期的主窗口,还会额外弹出一个名为“tk”的空白白色窗口。删除相关代码行后空白窗口消失,但仅注释代码无法解决问题。
问题原因
- 调用
ctk.CTkToplevel()创建顶级窗口时,必须依赖一个已存在的ctk.CTk()主窗口实例作为根窗口。 - 你的代码中,登录成功后先执行
loginWindow.destroy()销毁了初始的ctk.CTk()登录窗口,随后才创建ctk.CTkToplevel()主窗口。此时没有活跃的CustomTkinter根窗口,Tkinter会自动创建一个默认的空白根窗口(就是那个名为"tk"的窗口)。
解决方案
提供两种简单有效的解决方式:
方式一:将主窗口改为ctk.CTk()实例
把Create_main_window里的CTkToplevel改成CTk,让它成为新的独立主窗口,不再依赖已销毁的登录窗口:
def Create_main_window(): global mainWindowVar # 替换CTkToplevel为CTk,创建独立的主窗口 mainWindow = ctk.CTk() mainWindow.title("Social") mainWindow.geometry("650x650") mainWindow.resizable(0,0) mainWindowVar = mainWindow ctk_textbox_scrollbar = ctk.CTkScrollbar(mainWindow) ctk_textbox_scrollbar.grid(row=0, column=1, sticky="ns") createButton = ctk.CTkButton(master=mainWindow, text="+ New Post", command=new_post) createButton.place(rely=0.05, relx=0.97, anchor=tk.E) # 启动新窗口的主循环 mainWindow.mainloop()
方式二:调整窗口销毁顺序
先创建主窗口,再销毁登录窗口,确保创建CTkToplevel时存在活跃的根窗口:
def Button_handler(): uName = uNameEntry.get() uPassword = uPasswordEntry.get() for name in loginData: if name == uName: if uPassword == loginData.get(uName)[passwordNum]: invalidLogin.place_forget() Create_main_window() # 先创建主窗口 loginWindow.destroy() # 再销毁登录窗口 return invalidLogin.place(relx=0.5, rely=0.35, anchor=tk.N)
完整修改后的代码(方式一示例)
import customtkinter as ctk import tkinter as tk import tkinter.font as font passwordNum = 0 visible = False textentry = None titleentry = None mainWindowVar = None ctk.set_default_color_theme("green") loginWindow = ctk.CTk() loginWindow.geometry("500x500") button_font = font.Font(size=50) # 1.Name, 2.Password, 3. Perms loginData = {"1": ["1", ["post"]]} def Create_Post(master, windowHeight, windowWidth): distanceBetweenTopAndPost = (windowHeight / 100) * 0.1 distanceBetweenLeftAndPost = (windowWidth / 100) * 0.1 nameLabel = ctk.CTkLabel(master=master, text="test") nameLabel.place(relx=distanceBetweenLeftAndPost, rely=distanceBetweenTopAndPost) def Toggle_password_visibility(): global visible if visible == False: visible = True uPasswordEntry.configure(show="") togglePasswordBtn.configure(text="🤫") else: visible = False uPasswordEntry.configure(show="*") togglePasswordBtn.configure(text="👀") def Button_handler(): uName = uNameEntry.get() uPassword = uPasswordEntry.get() for name in loginData: if name == uName: if uPassword == loginData.get(uName)[passwordNum]: invalidLogin.place_forget() loginWindow.destroy() Create_main_window() return invalidLogin.place(relx=0.5, rely=0.35, anchor=tk.N) def Post_Button(master, windowHeight, windowWidth): global textentry, titleentry textentrytext = textentry.get("1.0", "end-1c") text = titleentry.get() Create_Post(master, windowHeight, windowWidth) def new_post(): global titleentry, textentry, mainWindowVar post_window = ctk.CTkToplevel(mainWindowVar) # 显式指定主窗口为父容器 post_window.title("New Post") post_window.geometry("350x350") post_window.resizable(0,0) headingLabel = ctk.CTkLabel(master=post_window, text="Headline", fg_color="transparent") headingLabel.place(relx=0.06, rely=0.05, anchor=tk.W) textLabel = ctk.CTkLabel(master=post_window, text="Text", fg_color="transparent") textLabel.place(relx=0.05, rely=0.23) titleEntry = ctk.CTkEntry(master=post_window) titleEntry.place(relx=0.05, rely=0.15, anchor=tk.W) global titleentry titleentry = titleEntry textEntry = ctk.CTkTextbox(master=post_window, width=250, height=200) textEntry.place(relx=0.4, rely=0.6, anchor=tk.CENTER) global textentry textentry = textEntry postBtn = ctk.CTkButton(master=post_window, text="Post", width=30, height=30, command=lambda: Post_Button(mainWindowVar, post_window.winfo_height(), post_window.winfo_width())) postBtn.place(relx=0.85, rely=0.1, anchor=tk.W) def Create_main_window(): global mainWindowVar mainWindow = ctk.CTk() mainWindow.title("Social") mainWindow.geometry("650x650") mainWindow.resizable(0,0) mainWindowVar = mainWindow ctk_textbox_scrollbar = ctk.CTkScrollbar(mainWindow) ctk_textbox_scrollbar.grid(row=0, column=1, sticky="ns") createButton = ctk.CTkButton(master=mainWindow, text="+ New Post", command=new_post) createButton.place(rely=0.05, relx=0.97, anchor=tk.E) mainWindow.mainloop() invalidLogin = ctk.CTkLabel(loginWindow, text="Invalid password", text_color="red", fg_color="transparent") invalidLogin.place(relx=0.5, rely=0.38, anchor=tk.N) invalidLogin.place_forget() uNameEntry = ctk.CTkEntry(master=loginWindow, placeholder_text="Username") uNameEntry.place(relx=0.5, rely=0.17, anchor=tk.N) # 密码输入框 uPasswordEntry = ctk.CTkEntry(master=loginWindow, show="*", placeholder_text="Password") uPasswordEntry.place(relx=0.5, rely=0.27, anchor=tk.N) # 确认按钮 confirmButton = ctk.CTkButton(master=loginWindow, text="Login", command=Button_handler) confirmButton.place(relx=0.5, rely=0.40, anchor=tk.CENTER) togglePasswordBtn = ctk.CTkButton(master=loginWindow, text="👀", fg_color="transparent", command=Toggle_password_visibility, width=10, height=15, hover=False) togglePasswordBtn["font"] = button_font togglePasswordBtn.place(relx=0.65, rely=0.27) loginWindow.mainloop()
内容的提问来源于stack exchange,提问作者Latif
相关产品推荐
相关产品推荐

