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

Custom Tkinter使用pack_forget后出现重复添加按钮问题求助

问题分析

问题出在你每次调用loadSelectionFrame时,只是通过pack_forget隐藏了selectionFrame,但Frame内部的旧控件(包括之前的加号按钮)并没有被移除。当你再次调用loadSelectionFrame时,会在同一个Frame里新增一套标签、组合框和按钮,旧的按钮仍然存在,因此会出现两个加号按钮。

解决方案

方法一:清空Frame后再加载新控件

在loadSelectionFrame函数开头,先遍历selectionFrame的所有子控件并销毁它们,确保每次加载都是全新的控件:

修改后的完整代码:

import customtkinter
import tkinter

customtkinter.set_appearance_mode('dark')
customtkinter.set_default_color_theme('dark-blue') #dark-blue, blue, or green


def loadSelectionFrame(buttonCount=1):
    # 先清空selectionFrame内的所有旧控件
    for widget in selectionFrame.winfo_children():
        widget.destroy()
    
    selectionFrame.rowconfigure(buttonCount+2, weight=1)
    selectionFrame.columnconfigure(2, weight=1)
    selectionFrame.pack()

    fieldLabel = customtkinter.CTkLabel(master=selectionFrame, text="Choose Field")
    fieldLabel.grid(row=1, column=1, pady=12, padx=10)
    typeLabel = customtkinter.CTkLabel(master=selectionFrame, text="Choose Value")
    typeLabel.grid(row=1, column=2, pady=12, padx=10)
    for i in range(buttonCount):
        fieldsDropDown = customtkinter.CTkComboBox(master=selectionFrame, values=["Option 1", "Option 2"])
        fieldsDropDown.grid(row=i+2, column=1, pady=12, padx=10)
        typeDropDown = customtkinter.CTkComboBox(master=selectionFrame, values=["Option 1", "Option 2"])
        typeDropDown.grid(row=i+2, column=2, pady=12, padx=10)
    addMoreFieldsButton = customtkinter.CTkButton(master=selectionFrame, text="+", command=lambda: addMoreFields(buttonCount+1, selectionFrame))
    addMoreFieldsButton.grid(row=buttonCount+2, columnspan=3, pady=12, padx=10)

def addMoreFields(buttonCount, selectionFrame):
    selectionFrame.pack_forget()
    loadSelectionFrame(buttonCount)
    
root = customtkinter.CTk()
mainFrame = customtkinter.CTkFrame(master=root)
mainFrame.pack(pady=20,padx=60, fill='both', expand=True)
selectionFrame = customtkinter.CTkFrame(master=mainFrame)

loadSelectionFrame()

root.mainloop()

方法二:直接新增组合框(更高效)

不需要每次销毁重建所有控件,只需要在点击按钮时新增一行组合框,并调整按钮的位置:

修改后的代码:

import customtkinter
import tkinter

customtkinter.set_appearance_mode('dark')
customtkinter.set_default_color_theme('dark-blue') #dark-blue, blue, or green

current_row = 2  # 记录当前要新增组合框的行号
add_button = None  # 保存加号按钮的引用

def loadSelectionFrame():
    global current_row, add_button
    selectionFrame.rowconfigure(0, weight=1)
    selectionFrame.columnconfigure(2, weight=1)
    selectionFrame.pack()

    fieldLabel = customtkinter.CTkLabel(master=selectionFrame, text="Choose Field")
    fieldLabel.grid(row=1, column=1, pady=12, padx=10)
    typeLabel = customtkinter.CTkLabel(master=selectionFrame, text="Choose Value")
    typeLabel.grid(row=1, column=2, pady=12, padx=10)
    
    # 初始化第一行组合框
    fieldsDropDown = customtkinter.CTkComboBox(master=selectionFrame, values=["Option 1", "Option 2"])
    fieldsDropDown.grid(row=current_row, column=1, pady=12, padx=10)
    typeDropDown = customtkinter.CTkComboBox(master=selectionFrame, values=["Option 1", "Option 2"])
    typeDropDown.grid(row=current_row, column=2, pady=12, padx=10)
    current_row +=1
    
    # 创建加号按钮
    add_button = customtkinter.CTkButton(master=selectionFrame, text="+", command=addMoreFields)
    add_button.grid(row=current_row, columnspan=3, pady=12, padx=10)

def addMoreFields():
    global current_row, add_button
    # 新增一行组合框
    fieldsDropDown = customtkinter.CTkComboBox(master=selectionFrame, values=["Option 1", "Option 2"])
    fieldsDropDown.grid(row=current_row, column=1, pady=12, padx=10)
    typeDropDown = customtkinter.CTkComboBox(master=selectionFrame, values=["Option 1", "Option 2"])
    typeDropDown.grid(row=current_row, column=2, pady=12, padx=10)
    current_row +=1
    # 调整加号按钮的位置到新的行
    add_button.grid(row=current_row, columnspan=3, pady=12, padx=10)
    
root = customtkinter.CTk()
mainFrame = customtkinter.CTkFrame(master=root)
mainFrame.pack(pady=20,padx=60, fill='both', expand=True)
selectionFrame = customtkinter.CTkFrame(master=mainFrame)

loadSelectionFrame()

root.mainloop()

说明

  • 方法一通过widget.destroy()彻底删除旧控件,确保每次加载都是全新的内容,适合简单场景。
  • 方法二更高效,只新增需要的控件,避免重复创建标签和销毁控件,适合频繁添加的场景。

内容的提问来源于stack exchange,提问作者Dorian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 17:56:07