You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在关闭tkinter根窗口时保存Canvas矩形的几何参数?

Tkinter窗口关闭时保存Canvas矩形坐标问题解决

问题分析

  • 事件多次触发:<Destroy>事件会在每个组件(根窗口、Canvas、按钮等)被销毁时触发,且事件会向上冒泡到父组件,所以根窗口会收到多次事件回调,导致处理函数被重复调用。
  • Canvas存在却无法获取矩形坐标:当根窗口的<Destroy>事件触发时,Canvas对应的Tcl内部命令已被销毁,winfo_width()依赖的窗口管理器信息尚未清理所以能返回值,但canvas.coords()需要调用Canvas的专属Tcl命令,此时已失效,因此报错。

解决方案

方法1:使用WM_DELETE_WINDOW协议(推荐)

该协议在用户点击窗口关闭按钮时触发,此时窗口未进入销毁流程,所有组件都处于正常状态,可安全获取矩形坐标。

修改后的代码:

import tkinter as tk
import json

def save_rect_coords():
    coords = canvas.coords(box)
    print("保存矩形坐标:", coords)
    # 实际项目中可保存到文件,示例:
    # with open("rect_config.json", "w") as f:
    #     json.dump(coords, f)

def on_closing():
    save_rect_coords()
    root.destroy()

def print_data(caller):
    global trial_count
    trial_count += 1
    print(f'---------- trial {trial_count} called from {caller} ------------')
    print('try canvas.winfo_width()', canvas.winfo_width())
    print('try canvas.coords(box)', canvas.coords(box))

def btn():
    print_data('button')

trial_count = 0
root = tk.Tk()
# 绑定窗口关闭协议,替代Destroy事件
root.protocol("WM_DELETE_WINDOW", on_closing)

canvas = tk.Canvas(root)
canvas.pack()
box = canvas.create_rectangle(20, 20, 100, 50)
tk.Button(root, text='点击打印', command=btn).pack()

# 可选:加载上次保存的坐标
# try:
#     with open("rect_config.json", "r") as f:
#         saved_coords = json.load(f)
#         canvas.coords(box, *saved_coords)
# except FileNotFoundError:
#     pass

root.mainloop()

方法2:实时保存矩形坐标

如果需要跟踪矩形的移动/拉伸操作,可在每次修改时就保存坐标,关闭窗口时直接读取已保存的值,无需在关闭事件中临时获取:

import tkinter as tk
import json

current_coords = [20,20,100,50]

def update_coords(event):
    global current_coords
    current_coords = canvas.coords(box)
    # 实时保存到文件
    # with open("rect_config.json", "w") as f:
    #     json.dump(current_coords, f)

def on_closing():
    print("保存的矩形坐标:", current_coords)
    root.destroy()

trial_count = 0
root = tk.Tk()
root.protocol("WM_DELETE_WINDOW", on_closing)

canvas = tk.Canvas(root)
canvas.pack()
box = canvas.create_rectangle(*current_coords)
# 绑定矩形拖拽/拉伸事件(需自行实现完整拖拽逻辑)
canvas.tag_bind(box, '<B1-Motion>', update_coords)

tk.Button(root, text='点击打印', command=lambda: print_data('button')).pack()

def print_data(caller):
    global trial_count
    trial_count += 1
    print(f'---------- trial {trial_count} called from {caller} ------------')
    print('try canvas.winfo_width()', canvas.winfo_width())
    print('try canvas.coords(box)', current_coords)

root.mainloop()

验证效果

  • 点击按钮仍能正常打印Canvas宽度和矩形坐标
  • 关闭窗口时仅触发一次保存逻辑,可成功获取并保存矩形坐标,无报错

内容的提问来源于stack exchange,提问作者VanDee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:13:13