Search code examples
pythonpython-2.7functiontkintercursor

Tkinter .icursor(*arg) strange behaviour


I'd like to create an Entry with Tkinter where the user can type its telephone number and the text dynamically changes in order that once finished it becomes like +34 1234567890.

In my code the function .icursor(n), used to set the cursor position, at first does not work properly, but then, surpassed the prefix, it does.

This is my code snippet (It belongs to a much larger one).

from Tkinter import *

def TelephoneCheck(self,Vari):
    Plain = Vari.get()
    Plain = list(Plain)

    Plain_flat = []
    for element in Plain:
        try:
            check = int(element)
            Plain_flat.append(element)
        except: pass

    if len(Plain_flat) > 2:
        Plain_flat.insert(2,' ')

    Plain = ''.join(Plain_flat)
    Plain = '+'+Plain

    self.istn.set(Plain)

    self.InsertTelephoneNumber.icursor(len(Plain))



def CreateInsertTelephoneNumber(self,X,Y,color='white'):
    self.istn = StringVar()
    self.istn.trace('w', lambda name, index, mode, istn=self.istn: self.TelephoneCheck(istn))
    self.InsertTelephoneNumber = Entry(Body,textvariable=self.istn)
    self.InsertTelephoneNumber.config(bg=color)
    self.InsertTelephoneNumber.place(height=20,width=230,y=Y+27,x=X+245)



def LabelBody(self,X,Y):
    TelephoneText = Label(Body,text='Telephone Number *')
    TelephoneText.place(y=Y+4,x=X+243)
    self.CreateInsertTelephoneNumber(X,Y)

As you see, theoretically, the position should be setted at the end of the string everytime the user adds a number. I can not understand why it works like a charm only after the prefix and not when the first number is typed (It results as +(Cursor here)3 instead of +3(Cursor here)).

If more code is needed I will update the post.

Thanks for your time and help!


Solution

  • The problem is that you're setting the cursor, but then the underlying widget sets the cursor the way it normally does. Because you're inserting characters into the widget in the middle of Tkinter processing a key press and release, it gets confused. For example, on the very first keystroke it thinks the cursor should be at position 1, but you've inserted a character after that position so the cursor ends up between characters.

    The simplest solution is to schedule your change to happen after the default behavior by using after_idle:

    Body.after_idle(self.InsertTelephoneNumber.icursor, len(Plain))