拦截关闭窗口按钮(Tkinter窗口)引发Tcl错误

2 投票
1 回答
1099 浏览
提问于 2025-04-18 08:42

我有一个程序,它会在某个时候打开一个新窗口,这个窗口里有很多按钮和小工具,供用户选择和操作。这个窗口的定义如下:

def window(self,master):
  def close(self):
    # change some variables
    self.destroy()
  top = self.top = Toplevel()
  # Several lines of buttons
  top.lift()
  top.protocol("WM_DELETE_WINDOW",close(self))

最开始我在窗口里放了一个关闭按钮,这样用户可以很方便地关闭窗口。但是我发现,如果用户直接点击窗口右上角的“X”按钮,这个关闭功能就不会被调用,这样后面会出现很多问题。我在这个网站上看到有人提到过“WM_DELETE_WINDOW”,我试着用了一下,但却遇到了一个奇怪的错误:

  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1630, in wm_protocol
    'wm', 'protocol', self._w, name, command)
TclError: bad window path name ".33862072"

我猜可能是窗口的ID搞错了,所以无法捕捉到这个事件。我的问题是,这种情况是真的吗?如果是真的,我该怎么解决这个问题呢?

1 个回答

0

让我们来看看这行代码:

top.protocol("WM_DELETE_WINDOW",close(self))

这行代码的意思是“立刻调用函数 close(self),并把结果赋值给协议处理器。”你看出问题了吗?它是立刻调用 close,很可能在 self 还没有完全构建好之前就调用了。你并不想让这个函数被“调用”,而是想传递一个对这个函数的“引用”。

close 改成 self 的一个方法(而不是一个嵌套的函数),然后把对 top.protocol 的调用改成这样(注意后面没有括号):

top.protocol("WM_DELETE_WINDOW", self.close)

如果你更喜欢保留嵌套函数,可以使用 lambda:

top.protocol("WM_DELETE_WINDOW", lambda window=self: close(window))

撰写回答