CustomTkinter字典程序:翻页按钮与开关交互报错排查
字典程序翻页后开关操作报错问题及解决方法
我使用CustomTkinter开发一款字典程序,程序包含翻页按钮与功能开关。点击翻页按钮会销毁前10组组件并生成新10组以实现分页效果。先开启开关再点击翻页按钮无报错,但先点击翻页按钮再操作开关则会触发报错。开关用于批量激活组件内的编辑按钮,以下是可复现的简化代码:
import customtkinter customtkinter.set_appearance_mode('light') customtkinter.set_default_color_theme('dark-blue') root = customtkinter.CTk() root.geometry('750x800') root.title('My dictionary') root.resizable(width=False, height=False) database_example = ( [1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4], [5, 5, 5], [6, 6, 6], [7, 7, 7], [8, 8, 8], [9, 9, 9], [10, 10, 10], [11, 11, 11], [12, 12, 12], [13, 13, 13], [14, 14, 14], [15, 15, 15], [16, 16, 16], [17, 17, 17], [18, 18, 18], [19, 19, 19], [20, 20, 20], [21, 21, 21], [22, 22, 22], [23, 23, 23], [24, 24, 24], [25, 25, 25], [26, 26, 26], [27, 27, 27], [28, 28, 28], [29, 29, 29], [30, 30, 30], [31, 31, 31], [32, 32, 32], [33, 33, 33], [34, 34, 34], [35, 35, 35], [36, 36, 36], [37, 37, 38], [39, 39, 39], [40, 40, 40] ) start_pos = 0 end_pos = 10 class WordBox: button_container = [] instances = [] def __init__(self, word='', translation='', context='', ): self.instances.append(self) word_fontsize = 23 translation_fontsize = 23 self.outer_frame = customtkinter.CTkFrame(master=scroll_frame, width=700, height=150, fg_color='#AED5D5') self.outer_frame.pack(pady=12, padx=10, side='top') self.inner_LabelWord = customtkinter.CTkLabel(master=self.outer_frame, text=word, fg_color='#C9D1D8', text_color='#0B7BDE', font=('Arial Black', word_fontsize), width=450, height=50, anchor='nw') self.inner_LabelWord.grid(row=0, column=0) self.inner_LabelTranslation = customtkinter.CTkLabel(master=self.outer_frame, text=translation, fg_color='#C9D1D8', text_color='black', font=('Yu Gothic UI Semibold', translation_fontsize), width=450, height=50, anchor='nw') self.inner_LabelTranslation.grid(row=1, column=0) self.inner_LabelContext = customtkinter.CTkLabel(master=self.outer_frame, text=context, fg_color='#908D8B', text_color='black', font=('Dubai', 14), width=450, height=50, anchor='nw') self.inner_LabelContext.grid(row=2, column=0) self.inner_PicFrame = customtkinter.CTkFrame(master=self.outer_frame, fg_color='#48E5E0', width=150, height=150) self.inner_PicFrame.grid(row=0, column=1, rowspan=3) self.inner_PicLabel = customtkinter.CTkLabel(master=self.inner_PicFrame, text='PICTURE') self.inner_PicLabel.pack() self.inner_Button = customtkinter.CTkButton(master=self.outer_frame, width=50, height=150, text='O', font=('', 20), fg_color='#C9D1D8', hover_color='#FFA60B', state='disabled') self.inner_Button.grid(row=0, column=2, rowspan=3) self.button_container.append(self.inner_Button) def switcher(): if switch_var.get() == 'on': for i in WordBox.button_container: i.configure(state='normal') if switch_var.get() == 'off': for i in WordBox.button_container: i.configure(state='disabled') def start_programm(db): for word in db[:10]: WordBox( word=word[0], translation=word[1], context=word[2], ) def rightbutton(): global start_pos global end_pos start_pos += 10 end_pos += 10 for item in WordBox.button_container: del item for instance in WordBox.instances: instance.inner_Button.destroy() instance.outer_frame.destroy() instance.inner_PicFrame.destroy() instance.inner_LabelContext.destroy() instance.inner_LabelTranslation.destroy() instance.inner_LabelWord.destroy() del instance for word in database_example[start_pos:end_pos]: WordBox( word=word[0], translation=word[1], context=word[2], ) switch_var = customtkinter.StringVar(value="off") switch = customtkinter.CTkSwitch(master=root, text='', command=switcher, variable=switch_var, onvalue="on", offvalue="off", progress_color='#E5611F') switch.place(relx=0.862, rely=0.26) scroll_frame = customtkinter.CTkScrollableFrame(master=root, width=700, height=500) scroll_frame.place(relx=0.01, rely=0.3) right_button = customtkinter.CTkButton(master=root, text='>>', command=rightbutton, width=35, height=30, corner_radius=17, fg_color='#817A7A', hover_color='#E5611F') right_button.place(relx=0.12, rely=0.26) start_programm(database_example) root.mainloop()
解决方案
原代码中del运算符未按预期清空容器内的引用,导致翻页后button_container和instances中仍残留已销毁组件的无效引用,操作开关时会尝试访问这些无效对象引发报错。重写翻页按钮的回调函数,使用clear()方法彻底清空两个容器,问题得以解决,重写后的函数如下:
def rightbutton(): global start_pos global end_pos start_pos += 10 end_pos += 10 for instance in WordBox.instances: instance.inner_Button.destroy() instance.outer_frame.destroy() instance.inner_PicFrame.destroy() instance.inner_LabelContext.destroy() instance.inner_LabelTranslation.destroy() instance.inner_LabelWord.destroy() WordBox.button_container.clear() WordBox.instances.clear() for word in database_example[start_pos:end_pos]: WordBox( word=word[0], translation=word[1], context=word[2], )
内容的提问来源于stack exchange,提问作者mr.Jenkins
相关产品推荐
相关产品推荐

