ghost chars in Tkinter.Entry

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Strider1066
    New Member
    • Aug 2007
    • 11

    #1

    ghost chars in Tkinter.Entry

    Is it a bug or a feature?

    I'm trying to sub-class an Entry widget that displays a template (i.e. '____-__-__') for users and does keystroke validation. It is starting to work but with one problem. Every key is echoed in the Entry widget. If I were to type a '2', '22__-__-__' is displayed. The next entry replaces the first duplicate with another, that is if I were to then type a '3' the display now shows '233__-__-__', and so on. The correct data is held by the widget as shown by a entry.get() but the display is wrong.

    I have started poking at the code with a sharp stick, Please, any suggestions.

    steve

    Code:
    from Tkinter import *
    import pdb
    
    class entryDate(Entry):
        def __init__(self, parent=None, template="@2###@-##@-##"):
            Entry.__init__(self, parent)
            self.ptr=-1                 # '-1' to accomadate nextwriteable's ptr +=mov
            self.next=object        #for linked list
            self.prior=object       #for linked list
            self.refrList=self.makeReferenceList(template)
            self.workingList=self.makeWorkingList(self.refrList)
            self.bind('<Key>', self.onKeyPress)
            self.config(self, background = "green", width = 10) 
            self.insert(0, (''.join(self.workingList)))
            self.nextWriteable(1)
    
        def makeReferenceList(self, templateStr):
            ts = templateStr
            tl=[]
            i=0
            while i < len(ts):
                if ts[i]=='@':
                    tl.append(ts[i:i+2])
                    i += 2
                else:
                    tl.append(ts[i : i +1])
                    i+=1
            return tl
        
        def makeWorkingList(self, tmplt):
            s=[]
            displayChar = '_'
            for itm in tmplt:
                if itm[0]=='@':
                    s.append(itm[1])
                else:
                    s.append(displayChar)
            return s
    
        def onKeyPress(self, event):
            if event.char==event.keysym: #normal key
                self.delete(0, END)
                if self.refrList[self.ptr]=='#': #ie writeable
                    if event.char.isdigit():
                        self.workingList[self.ptr]=event.char
                        self.insert(0, (''.join(self.workingList)))
                        self.nextWriteable(1)
                    else:                                   # if alpha key
                        s = ''.join(self.workingList)
                        self.insert( 0, (''.join(self.workingList)))
            elif len(event.char)==1:        # punctuation
                pass
            else:
                pass
    
        def nextWriteable(self, mov):
            self.ptr += mov
            if self.ptr < 0:
                self.ptr=len(self.refList)   #replace with linked list
                self.icursor=self.ptr           # ''
                self.prior.focus_set()
            elif self.ptr == len(self.refrList):
                self.ptr=0                    #replace with linked list
                self.icursor=0                # ''
            elif self.refrList[self.ptr][0]=='@':
                self.nextWriteable(mov)
            else:
                self.icursor(self.ptr)
    
    if __name__=='__main__':
        root = Tk()
        entr= entryDate(root)
        entr.pack()
        entr.focus_set()
        root.mainloop()
  • jlm699
    Contributor
    • Jul 2007
    • 314

    #2
    The problem here is that while you have binded the keypress event to your function onKeyPress, it is an instance binding only, Tkinter is still performing its own keypress event at the root level. Remove the binding from your class's __init__ and place it after the line as such:
    [code=python]
    if __name__=='__ma in__':
    root = Tk()
    entr= entryDate(root)
    root.bind('<Key >',entr.onKeyPr ess)
    entr.pack()
    entr.focus_set( )
    root.mainloop()[/code]

    Comment

    • Strider1066
      New Member
      • Aug 2007
      • 11

      #3
      Thank you,
      That worked like a champ.

      Comment

      Working...