使用SimpleGraphics包装器时,Tkinter画布随窗口动态缩放的无限循环问题求助
使用SimpleGraphics包装器时,Tkinter画布随窗口动态缩放的无限循环问题求助
嗨,我太懂你这种被指定包装器限制,还踩了Tkinter事件循环坑的痛苦了!先帮你把问题拆明白:
你把<Configure>事件绑定到了root窗口上,当你在回调里调用SG.__canvas.config()修改画布尺寸时,画布的配置变化会再次触发root的<Configure>事件(Tkinter里子组件的变更有时候会冒泡到父组件),直接形成了「窗口尺寸变→改画布→触发窗口事件→再改画布」的死循环。
针对你不能修改包装器的限制,给你两个不用动核心类的可行方案,随便选一个都能解决问题:
方案1:记录窗口尺寸,只处理真实的窗口变化
我们可以维护一个「上一次窗口尺寸」的记录,只有当窗口宽高真的发生变化时,才去调整画布大小,这样就能过滤掉画布修改触发的重复事件:
import SimpleGraphics as SG # 记录上一次的窗口尺寸,后续在main里初始化 last_win_width = 0 last_win_height = 0 def onResize(event): global last_win_width, last_win_height # 只处理root窗口的事件,且尺寸确实和上一次不一致 if event.widget == SG.__master: current_width = event.width current_height = event.height if current_width != last_win_width or current_height != last_win_height: # 更新记录的尺寸 last_win_width, last_win_height = current_width, current_height # 调整画布尺寸并清空 SG.__canvas.config(width=current_width, height=current_height) SG.clear() def main(): root = SG.__master # 初始化窗口尺寸记录 global last_win_width, last_win_height last_win_width = root.winfo_width() last_win_height = root.winfo_height() root.bind("<Configure>", onResize) if __name__ == "__main__": main()
方案2:用开关标记跳过手动触发的事件
我们加一个全局开关,当我们正在手动调整画布尺寸时,直接跳过<Configure>事件的处理,等调整完再把开关打开,从根源上阻断循环:
import SimpleGraphics as SG # 标记是否正在调整画布尺寸,初始为关闭状态 is_resizing = False def onResize(event): global is_resizing # 如果是我们自己触发的调整,直接跳过 if is_resizing: return # 只处理root窗口的尺寸变化事件 if event.widget == SG.__master: is_resizing = True # 打开开关,避免循环 SG.__canvas.config(width=event.width, height=event.height) SG.clear() is_resizing = False # 调整完成,关闭开关 def main(): root = SG.__master root.bind("<Configure>", onResize) if __name__ == "__main__": main()
最后给你提两个小细节:
- 你原来代码里的
if event.height and event.width:可以去掉,root窗口的<Configure>事件里这两个值都是有效的,不会为空; SG.clear()放在画布尺寸修改完成后调用是对的,这样能确保清除的是新尺寸的画布内容。
备注:内容来源于stack exchange,提问作者skelyvelocirap
相关产品推荐
相关产品推荐

