滑动customtkinter的CTkSlider触发RecursionError的原因排查
问题分析与解决:CTkSlider值传递引发递归错误
问题背景
尝试通过独立的Variables类将CTkSlider的实时值从顶层窗口传递到主窗口,滑动滑块时触发RecursionError: maximum recursion depth exceeded错误。
错误原因分析
- 错误的类继承设计:
Variables类错误继承了App(GUI应用主类),但Variables的定位是值传递中间层,并非GUI实例。且Variables的__init__未调用父类App的初始化方法,导致App的属性(如app_condition)未被正确初始化。 - 无限递归的属性访问:当
value_setter中访问self.app_condition时,由于该属性未被初始化,tkinter的__getattr__方法会被触发,尝试从self.tk中查找该属性。但self.tk同样未被初始化,导致__getattr__被无限递归调用,最终触发递归深度超限错误。 - 无效的实例关联:
ToplevelWindow中创建的Variables实例是独立于主窗口App的新对象,根本无法将滑块值传递到主窗口,完全偏离了值传递的设计目的。
修复方案
核心调整方向
- 取消
Variables对App的继承,将其改为纯数据传递类,或直接使用customtkinter内置的变量类型(如CTkIntVar) - 让顶层窗口持有主窗口
App的实例引用,直接调用主窗口的方法更新值,建立正确的实例关联
修复后的代码示例
import customtkinter class ToplevelWindow(customtkinter.CTkToplevel): def __init__(self, master_app, *args, **kwargs): super().__init__(*args, **kwargs) self.master_app = master_app # 持有主窗口实例引用 self.slider = customtkinter.CTkSlider( self, height=29, from_=0, to=100, number_of_steps=10, progress_color="#19A7CE", button_color="#FB2576", command=self.get_value ) self.slider.grid() def get_value(self, value): # 直接调用主窗口的更新方法传递滑块值 self.master_app.update_app_variable(int(value)) class App(customtkinter.CTk): def __init__(self): super().__init__() self.toplevel_window : customtkinter.CTkToplevel = None self.app_variable : int = 9 self.app_variable_1 : tuple = None self.app_variable_2 : float = 1.5 self.app_condition : float = 0.5 self.button = customtkinter.CTkButton(master=self, command=self.open_toplevel) self.button.grid() def open_toplevel(self): if self.toplevel_window is None or not self.toplevel_window.winfo_exists(): # 创建顶层窗口时传入主窗口实例 self.toplevel_window = ToplevelWindow(master_app=self, master=self) else: self.toplevel_window.focus() def value_setter(self, size=50): if self.app_condition < 1: self.app_variable_1 = (size, size * self.app_variable_2) else: self.app_variable_1 = (size * self.app_variable_2, size) # 可以在这里添加打印,验证值是否更新 print(f"更新后的app_variable_1: {self.app_variable_1}") def update_app_variable(self, size=50): self.value_setter(size) if __name__ == "__main__": app = App() app.mainloop()
额外优化建议
如果需要更灵活的变量绑定,可以使用customtkinter的内置变量类型,示例如下:
# 在App类中定义绑定变量 self.slider_var = customtkinter.CTkIntVar(value=50) # 顶层窗口中直接绑定该变量 self.slider = customtkinter.CTkSlider( self, height=29, from_=0, to=100, number_of_steps=10, progress_color="#19A7CE", button_color="#FB2576", variable=self.master_app.slider_var ) # 主窗口可以通过trace方法监听变量变化 self.slider_var.trace_add("write", lambda *args: self.update_app_variable(self.slider_var.get()))
内容的提问来源于stack exchange,提问作者duruburak
相关产品推荐
相关产品推荐

