不同绑定方式的不同结果?

Different results on different ways of binding?

在下面的代码中,我将键绑定到文本小部件。根据绑定完成的方式,当在小部件中键入 'x' 时,我会得到不同的结果。

为什么 bind 和 bind_all 的输出不同? 我应该如何使用所有三种变体,以便它们都给出相同的结果?

import tkinter as tk

class Q_bind(tk.Text):
    def __init__(self):
        tk.Text.__init__(self)

        self.bind("<Key>", self._insert_a)    #-> 'a\nx' with break a!
        #self.bind_class("<Key>", self._insert_a) # -> 'x' Replace with:
        #self.bind_class("Text", "<Key>", self._insert_a) # -> 'a'!!
        #self.bind_all("<Key>", self._insert_a)   # -> 'xa\n'
        print(self.bindtags())           #shows the bind-tags

    def _insert_a(self, event=None):
        print(event.char)
        self.insert('end' ,"a\n")
        return 'break'              #added

if __name__ == "__main__":
    app = Q_bind()
    app.pack(fill="both", expand='y')
    app.master.geometry('400x400')
    app.mainloop()

您不能使用所有三个绑定并获得相同的结果1,因为结果取决于小部件的顺序绑定标签 .

每个小部件都有一组有序的绑定标签。绑定实际上附加到这些标签而不是实际的小部件。正好第一个bind标签是widget的名字

默认情况下,小部件按以下顺序具有以下绑定标签:

  1. 小部件本身
  2. 小部件 class(内部 tk class,不是 tkinter class)
  3. 小部件顶层(或根 window)
  4. "all"

当小部件上发生事件时,会发生以下四种情况:

  1. 如果小部件具有与事件匹配的绑定,则处理该绑定
  2. 如果小部件 class 具有与事件匹配的绑定,则处理该绑定
  3. 如果小部件的顶层(或根)具有与事件匹配的绑定,则处理该绑定
  4. 如果 "all" 上存在绑定,则处理该事件。

在任何时候,如果绑定 returns 文字字符串 "break",则不会处理更多绑定。在不返回 "break" 的情况下,处理了所有四个事件处理程序。如果您的小部件绑定返回 "break",则不会处理 class、顶层和 "all" 绑定。

在将 <Key>bind_all 绑定的特定情况下,会发生以下情况:

  1. 小部件没有与事件匹配的绑定,因此什么都不做
  2. 小部件 class 具有 绑定,因此已处理。在这种情况下,密钥的字母被插入到小部件中
  3. 小部件的 toplevel/root 没有绑定,所以什么都不做
  4. "all" 标记具有绑定,因此它将插入 "a\n"

因为 "all" 的绑定发生在 小部件 class 的绑定之后,返回 "break" 没有效果,无法阻止除了 您的自定义行为之外,插入 "a" 的默认行为。

绑定标签是一种非常漂亮的事件处理方式。多年来,我使用过至少六种不同语言的不同 GUI 工具包,没有什么能比得上 tk 的绑定标签机制的强大功能。


1 实际上,您 可以 通过添加或删除绑定标签或更改绑定顺序来获得所有三个相同的行为标签。您可以使用 bindtag 方法执行此操作。很少需要这样做,但对于某些特殊情况来说非常方便。