-1

I have been working on one application where in I want to autocomplete things like brackets round curly square. I had done that using the insert method of tkinter with the tk.INSERT constant as index like so:

def autocomplete(self, val) :
    if val == '(' :
        self.insert(tk.INSERT, ')')
    elif val == '{' :
        self.insert(tk.INSERT, '}')
    elif val == '[' :
        self.insert(tk.INSERT, ']')
    elif val == '\'' :
        self.insert(tk.INSERT, '\'')
        self.mark_set('sentinel', str(float(self.index(tk.INSERT)) - 0.1))
    elif val == '\"' :
        self.insert(tk.INSERT, '\"')
        self.mark_set('sentinel', str(float(self.index(tk.INSERT)) - 0.1))
    elif val == ':' :
        text = self.get(1.0, tk.INSERT).strip().replace(' ', '')
        
        if text[(text.index(':') - 1) : text.index(':')] == ')' :
            self.insert(tk.INSERT, '\n\t')
    return

This is a function which is within a text widget where the init has the following bindings attached:

self.bind('(', lambda x : self.autocomplete('('))
self.bind('{', lambda x : self.autocomplete('{'))
self.bind('[', lambda x : self.autocomplete('['))
self.bind(':', lambda x : self.autocomplete(':'))
self.bind('\'', lambda x : self.autocomplete('\''))
self.bind('\"', lambda x : self.autocomplete('\"'))

And when I type any of these like lets take the e.g. of brackets, then it shows the output somewhat not right.

)(

Here is also a snapshot of the same:
The text widget's actual snapshot of the problem

You see I want the other bracket to appear at the end but it does not.

martineau
  • 119,623
  • 25
  • 170
  • 301
typedecker
  • 1,351
  • 2
  • 13
  • 25

1 Answers1

0

This is because the binding is triggered before the character is inserted in the text widget. To fix this you can bind to '<KeyRelease-..>' instead, where .. needs to be replaced by the keysym.

self.bind('<KeyRelease-parenleft>', lambda x : self.autocomplete('('))
self.bind('<KeyRelease-braceleft>', lambda x : self.autocomplete('{'))
self.bind('<KeyRelease-bracketleft>', lambda x : self.autocomplete('['))
self.bind('<KeyRelease-colon>', lambda x : self.autocomplete(':'))
self.bind('<KeyRelease-apostrophe>', lambda x : self.autocomplete('\''))
self.bind('<KeyRelease-quotedbl>', lambda x : self.autocomplete('\"'))

The keysym of special characters are not always the same for all OS, so here is a trick to find the keysym of any key on your system:

import tkinter as tk
root = tk.Tk()
root.bind('<Key>', lambda ev: print(ev.keysym))
root.mainloop()

Just press the key to get the keysym

j_4321
  • 15,431
  • 3
  • 34
  • 61
  • _tkinter.TclError: bad event type or keysym "apostrophe" – typedecker Sep 02 '20 at 14:04
  • is the event binding KeyRelease-( or something like that? – typedecker Sep 02 '20 at 14:05
  • @MatrixProgrammer The event binding is `''` where you need to replace 'a' by the keysym of the key (which might change with the OS for special keys). In my case `bind('', ...)` gives me a `TclError: bad event type or keysym "("`, I need to use 'parenleft' instead. You need to find what is the correct keysym for the quote for your system. – j_4321 Sep 02 '20 at 14:10
  • actually paren left was just an example the apostrophe is the one causing problem as you may see in the error, also if you know any link to find the keysms it will be really helpful. – typedecker Sep 02 '20 at 14:14
  • Ohk nevermind I found it manually testing, its for Windows just incase someone else needs it. – typedecker Sep 02 '20 at 14:17
  • Thx alot for that extra tip in the edit it will rly help me figure these out with other keys. – typedecker Sep 02 '20 at 14:20