Mark Zampedroni Mark Zampedroni - 3 months ago 27
Python Question

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!

Answer

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