绑定事件在键入的字符被放入条目之前运行

Bind event runs before character typed is put in entry

我正在用 tkinter 制作一个特殊的文本小部件,它应该有工作缩进。为了使缩进起作用,我将放下制表符的功能绑定到 Enter 按钮。此绑定在实际键入的字符之后进行绑定之前工作正常,但不适用于此功能。有人可以帮我吗?

工作绑定:

def double_parentheses(self, event):
        main_text_box_anchor = str(self.text.index("insert")).split(".")
        self.text.insert(INSERT, ")")
        self.text.mark_set(INSERT, str(main_text_box_anchor[0]) + "." + 
        str(int(main_text_box_anchor[1])))
#later in the code
scroll.text.bind("(", scroll.double_parentheses)

这会将括号按顺序排列,并在中间插入

不工作:

def new_line_indent(self, event):
        line = self.text.get("insert linestart", "insert lineend")
        editable_line = str(line)
        if editable_line != "":
            if editable_line[-1] == ":":
                if "\t" in editable_line:
                    for i in range(editable_line.count("\t")):
                        self.text.insert("insert", "\t")
                else:    
                    self.text.insert("insert", "\t")
            elif "\t" in editable_line:
                for i in range(editable_line.count("\t")):
                    self.text.insert("insert", "\t")
#Later in the code
scroll.text.bind("<Return>", scroll.new_line_indent)

这会放入制表符,但它是在创建新行之前完成的,我不明白为什么。我做错了什么?

This puts the tabs in but it does it BEFORE the new line is created and I can't figure out why.

简短的回答是您的绑定发生在 built-in 键绑定之前。因此,您的函数在 tkinter 实际插入换行符之前被调用。

您应该让代码插入换行符,执行其他操作,然后 return“中断”以防止发生默认行为。

有关如何处理绑定的更详尽的解释,请参阅this answer

这是一个工作示例:

def new_line_indent(self, event):
    # get the text of the current line
    line = self.text.get("insert linestart", "insert lineend")

    # insert the newline
    self.text.insert("insert", "\n")

    # insert indentation if line ends with ":"
    if line and line[-1] == ":":

        # get current indentation, then insert it
        leading_whitespace = self.get_leading_whitespace(line)
        self.text.insert("insert", leading_whitespace)

        # add an additional level of indentation
        self.text.insert("insert", "\t")

    # since we already inserted the newline, make sure that
    # the default bindings do not
    return "break"

def get_leading_whitespace(self, line):
    n = len(line) - len(line.lstrip())
    return line[:n]

除了 Bryan 建议的解决方案之外,您可以绑定 <KeyRelease-Return> 而不是 <Return>。然后回调会在添加换行符后执行:

    def new_line_indent(self, event):
        # get previous line
        line = self.text.get("insert-1c linestart", "insert-1c lineend")
        editable_line = str(line)
        if editable_line != "":
            for i in range(editable_line.count("\t")):
                self.text.insert("insert", "\t")
            if editable_line[-1] == ":":
                self.text.insert("insert", "\t")

...
#Later in the code
scroll.text.bind("<KeyRelease-Return>", scroll.new_line_indent)