wxPython布局断言错误:窗口已在sizer中,如何正确Detach?
错误信息
Traceback (most recent call last): File "/path/to/a/source.py", line ###, in onChoice self.__do_layout(self.GetPosition()[0], self.GetPosition()[1], self.GetSize().GetWidth()) File "/path/to/a/source.py", line ***, in __do_layout sizer_10.Add(self.notebook_1, 1, wx.EXPAND, 0) wx._core.wxAssertionError: C++ assertion ""!m_containingSizer"" failed at ./src/common/wincmn.cpp(2488) in SetContainingSizer(): Adding a window already in a sizer, detach it first!
已完成排查
- 在***行处,确认
self.notebook_1未被添加到其他sizer中 - 在***行前添加
sizer_10.Detach(self.notebook_1)语句无效果 - PyCharm调试显示***行执行前
sizer_10中无任何内容
下一步排查思路
检查
__do_layout调用频次:
在__do_layout开头添加日志打印,记录调用次数和self.notebook_1.GetContainingSizer()的返回值,确认事件触发时该方法是否被重复执行,以及每次调用时组件的sizer关联状态。精准解除组件的sizer绑定:
在***行前执行current_sizer = self.notebook_1.GetContainingSizer(),如果返回非None,直接调用current_sizer.Detach(self.notebook_1),再执行sizer_10.Add操作,避免只针对sizer_10做无效解绑。排查全量布局代码:
检查self.notebook_1初始化逻辑、其他事件处理函数、父类布局方法中是否有遗漏的sizer.Add(self.notebook_1)操作,确认是否存在其他代码路径将组件添加到了未知sizer中。验证sizer对象生命周期:
确认sizer_10是否为实例级持久对象,还是每次调用__do_layout时都会重新创建。如果是重复创建,旧的sizer实例可能仍持有组件引用,导致断言报错。强制解除组件的sizer关联:
在添加操作前调用self.notebook_1.SetContainingSizer(None)(底层操作,谨慎使用),强制清除组件当前的sizer绑定,再执行sizer_10.Add。定位PyCharm崩溃原因:
关闭PyCharm调试器的优化选项,改用print语句逐步输出关键变量状态,定位崩溃是否与sizer操作的时序、调试环境冲突有关。
内容的提问来源于stack exchange,提问作者jovian

