You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 21:33:07