如何解除Tkinter根窗口的所有绑定?

3
所以我有一个 Tkinter 应用程序,在第一个屏幕上有许多按钮,当你按下一个按钮时,你进入一个新的 "窗口"(基本上是销毁所有小部件并绘制需要的那些小部件)。有一个标准函数使用一些命令来销毁根节点上的每个子节点。我想添加一些代码,可以解除在根节点上绑定的所有绑定。在特定小部件上的绑定将被销毁,但在根节点上绑定的绑定仍然存在,并引起错误。
以下是销毁小部件的代码。
@staticmethod
def clear():
    for widget in guihandle.root.winfo_children():
        widget.destroy()

@staticmethod
def set(db,table):

    guihandle.clear()
    curW = Window(db,table)
    guihandle.current_Window = curW
    curW.initialize()
    guihandle.windows.push(curW)

(是的,我从sqlite3数据库中制作了基础GUI:P)

欢迎来到 Stack Overflow。如有需要,请包含错误消息,包括堆栈跟踪。 - Chris Travers
根据事件绑定的函数不同,我会得到各种不同的错误。因此,告诉您错误信息可能并没有太大帮助。 - nikosdcs
2个回答

5

Tkinter 没有能做到你想要的功能。你的应用程序需要跟踪它想要删除的绑定。

话虽如此,取决于你的实际问题有多复杂,可能会有其他解决方案。例如,绑定到根窗口的替代方法是绑定到自定义的 绑定标签 (也称为绑定标记或绑定标签)。然后,您需要将该标签添加到每个小部件以启用绑定,并从任何现有小部件中删除标签以有效地禁用绑定。


你能给我简要解释一下绑定标签是什么吗?我查了一下,但是没看懂。非常感谢你的帮助。 - nikosdcs
搜索这个网站。我已经用它们写了答案。 - Bryan Oakley

1

我知道我来晚了,但是如果你仔细查看你的代码并将每个widget.bind替换为下面的函数,该函数已经从这里获取并进行修改。

def bindWidget(widget: Widget, event, all:bool=False, func=None):
    # https://stackoverflow.com/a/226141/19581763
    '''Set or retrieve the binding for an event on a widget'''
    try:
        _ = widget.__dict__['bindings']
    except KeyError:
        has_binding_key = False
    else:
        has_binding_key = True
    if not has_binding_key:
        setattr(widget, 'bindings', dict())

    if func:
        if not all:
            widget.bind(event, func)
        else:
            widget.bind_all(event, func)
        widget.bindings[event] = func
    else:
        return(widget.bindings.setdefault(event, None))

然后该函数会通过设置一个名为bindings的属性来跟踪每个绑定,其中包含事件和函数。

例如:

label.bind('<Button-1>', label.destroy)

Will become:

bindWidget(label, '<Button-1>', func=label.destroy)

完成这些步骤后,您可以编写一个简单的函数来删除所有绑定和小部件:

def clear(self): # Self will be your Tk() instance
    """Clears everything on the window, including bindings"""
    for child in self.winfo_children():
        child.destroy()
    if not hasattr(self, 'bindings'):
        self.bindings = {}
    for event, func in self.bindings.items():
        self.unbind_all(event)
    self.bindings = {}

使用这种方法只有两个要注意的地方:

  1. 时间
    • 你需要检查代码并替换每个 widget.bind,如果你有很多绑定,那么这将花费很多时间。
  2. 可读性
    • bindWidget(label, '<Button-1>', func=label.destroy)label.bind('<Button-1>', label.destroy) 更难以阅读和理解。
编辑于 2022年8月11日

或者,你可以像这样销毁整个窗口并重新创建它:

window.destroy()
window = Tk()

然而,我不确定是否创建一个完整的Tcl解释器是好的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接