CustomTkinter中CTKButton状态修改不生效问题求助
解决CustomTkinter折叠按钮禁用后仍可点击的问题
问题原因
你通过bind("<Button-1>")给按钮绑定了点击事件,但CustomTkinter的CTkButton设置state=DISABLED时,仅会禁用按钮的默认command回调,不会阻止通过bind()绑定的自定义事件逻辑。这就是按钮状态显示为禁用,但点击依然触发折叠/展开的核心原因。
解决方案
有两种可行的修复方式,根据你的需求选择:
方案1:改用按钮的command参数(推荐)
将绑定事件的方式替换为按钮自带的command参数,这样设置state=DISABLED时会自动禁用回调逻辑:
修改CollapsibleFrame类的__init__方法中按钮初始化的代码:
# 初始化折叠按钮,用command替代bind self.collapsebuton = ctk.CTkButton(self, image=self.down_chevron, text="", command=self.collapse) self.collapsebuton.grid(row=0, column=1, padx=20, pady=20, sticky="e") # 删除原有的bind语句:self.collapsebuton.bind("<Button-1>", lambda event: self.collapse()) # 初始化展开按钮,用command替代bind self.uncollapsebuton = ctk.CTkButton(self, image=self.up_chevron, text="", command=self.uncollapse) self.uncollapsebuton.grid(row=0, column=1, padx=20, pady=20, sticky="e") # 删除原有的bind语句:self.uncollapsebuton.bind("<Button-1>", lambda event: self.uncollapse())
方案2:在绑定事件中检查按钮状态
如果必须保留bind的方式,需要在事件回调中先判断按钮状态,仅当状态为normal时执行逻辑:
修改__init__中的bind语句:
self.collapsebuton.bind("<Button-1>", lambda event: self.collapse() if self.collapsebuton.cget("state") == "normal" else None) self.uncollapsebuton.bind("<Button-1>", lambda event: self.uncollapse() if self.uncollapsebuton.cget("state") == "normal" else None)
完整修复后的代码示例(方案1)
import tkinter import customtkinter as ctk from PIL import Image ctk.set_appearance_mode("Dark") ctk.set_default_color_theme("dark-blue") appWidth, appHeight = 600, 700 class CollapsibleFrame(ctk.CTkFrame): """ Class to create a collapsible frame. Starts as collapsed. Row and Column are row and column of parent frame it should be gridded to """ def __init__(self, master, row:int=0,column:int=0,collapsed_text:str='',**kwargs): super().__init__(master, **kwargs) self.collapsed_text=collapsed_text # add widgets onto the frame, for example: self.label = ctk.CTkLabel(self) self.label.grid(row=0, column=0) self.title_label = ctk.CTkLabel(self, text=self.collapsed_text) self.title_label.grid(row=0, column=0) self.row=row self.column=column self.collapsed_widgets=[] # load icons self.down_chevron=ctk.CTkImage(Image.open("chevron_up.png"), size=(7, 7)) self.up_chevron = ctk.CTkImage(Image.open("chevron_down.png"), size=(7, 7)) # Add hide/unhide buttons self.collapsebuton = ctk.CTkButton(self, image=self.down_chevron,text="", command=self.collapse) self.collapsebuton.grid(row=0, column=1, padx=20, pady=20, sticky="e") self.uncollapsebuton = ctk.CTkButton(self, image=self.up_chevron,text="", command=self.uncollapse) self.uncollapsebuton.grid(row=0, column=1, padx=20, pady=20, sticky="e") def hide(self): """ Completely hides frame """ print('hiding') self.grid_forget() def unhide(self): """ Completely unhides frame """ print('unhiding') self.grid(row=self.row,column=self.column,sticky='ew') self.columnconfigure(0,weight=1) #self.rowconfigure(0, weight=1) def collapse(self): """ Collapses frame, leaving icon to uncollapse """ print('collapsing') # hide all known items sub_items=self.grid_slaves() for item in sub_items: self.collapsed_widgets.append(item) # save these items for if we want to un-hide them later item.grid_remove() # add back uncollapse button, title self.uncollapsebuton.grid() self.collapsebuton.grid_remove() self.title_label.grid() def uncollapse(self): """ Uncollapses frame, leaving icon to collapse """ print('uncollapsing') # unhide previously hidden widgets for item in self.collapsed_widgets: item.grid() self.collapsed_widgets.clear() self.unhide() self.collapsebuton.grid() self.uncollapsebuton.grid_remove() def disable_uncollapse(self): self.uncollapsebuton.configure(state=ctk.DISABLED) self.collapsebuton.configure(state='disabled') class App(ctk.CTk): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.title("My awesome window") self.geometry(f"{appWidth}x{appHeight}") self.columnconfigure(0, weight=1) create_vault_frame = CollapsibleFrame(self,row=0,column=0,collapsed_text="Panel1") create_vault_frame.uncollapse() new_label=ctk.CTkLabel(create_vault_frame,text='aaah') new_label.grid(row=1,column=0) create_vault_frame.disable_uncollapse() if __name__ == "__main__": app = App() app.mainloop()
内容的提问来源于stack exchange,提问作者Mr. T
相关产品推荐
相关产品推荐

