Home > OS >  Bind event runs before character typed is put in entry
Bind event runs before character typed is put in entry

Time:04-08

I am making a special Text widget with tkinter that is supposed to have working indentation. To get the indentation to work I binded the function that puts down the tabs to the Enter button. This binding worked fine before with the bind going after the actual typed character but it won't with this function. Can someone help me out?

Working bind:

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)

This puts the parentheses in order with the insert in the middle of them

Not working:

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. What am I doing wrong?

CodePudding user response:

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

The short answer is that your binding happens before the built-in key bindings. Thus, your function is called before the newline is actually inserted by tkinter.

You should have your code insert the newline, perform your other actions, then return "break" to prevent the default behavior from happening.

For a more thorough explanation of how bindings are processed, see this answer

CodePudding user response:

Other than the solution suggested by Bryan, you can bind <KeyRelease-Return> instead of <Return>. Then the callback will be executed after the newline is added:

    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)
  • Related