I want an Entry widget to accept a single digit only. Here's the attempt: --- import Tkinter as Tk class MyEntry(Tk.Entry): def __init__(self, parent, **kwargs): kwargs['validate']='key' # could also be 'all' -- has the same result kwargs['vcmd']=self.validate Tk.Entry.__init__(self, parent, **kwargs) def validate(self): print self.get() # diagnostic only if self.get() in [''] + list("123456789"): return True else: self.bell() return False if __name__=="__main__": main = Tk.Tk() main.e = MyEntry(main) main.e.grid() main.mainloop() --- I'd like to think this is straightforward, but No. I type in MyEntry: 1 printed value: (empty string) contents of MyEntry: 1 I type in MyEntry: 11 printed value: 1 contents of MyEntry: 11 I type in MyEntry: 111 (bell rings) printed value: 11 contents of MyEntry: 11 I type in MyEntry: a printed value: (empty string) contents of MyEntry: a I type in MyEntry: a1 (bell rings) printed value: a contents of MyEntry: a Near as I can tell, validate() is called after a key is pressed and displayed in the Entry widget, but *before* the pressed key has been added to MyEntry's contents. Hence, validate() has no way of knowing what the new keypress is -- it can only validate the past entry. Once it does so, the new key is added to MyEntry's contents. How can validate() discover the new keypress in order to validate it prior to addition to the Entry widget? Yikes! Thanks in advance, Jeff Cagle
On Wed, Oct 1, 2008 at 12:15 AM, Jeff Cagle <jrcagle@juno.com> wrote:
I want an Entry widget to accept a single digit only. Here's the attempt:
--- import Tkinter as Tk
class MyEntry(Tk.Entry):
def __init__(self, parent, **kwargs): kwargs['validate']='key' # could also be 'all' -- has the same result kwargs['vcmd']=self.validate Tk.Entry.__init__(self, parent, **kwargs)
def validate(self): print self.get() # diagnostic only if self.get() in [''] + list("123456789"): return True else: self.bell() return False
if __name__=="__main__": main = Tk.Tk() main.e = MyEntry(main) main.e.grid() main.mainloop()
---
I'd like to think this is straightforward, but No.
I type in MyEntry: 1 printed value: (empty string) contents of MyEntry: 1
I type in MyEntry: 11 printed value: 1 contents of MyEntry: 11
I type in MyEntry: 111 (bell rings) printed value: 11 contents of MyEntry: 11
I type in MyEntry: a printed value: (empty string) contents of MyEntry: a
I type in MyEntry: a1 (bell rings) printed value: a contents of MyEntry: a
Near as I can tell, validate() is called after a key is pressed and displayed in the Entry widget, but *before* the pressed key has been added to MyEntry's contents. Hence, validate() has no way of knowing what the new keypress is -- it can only validate the past entry.
validate does have a way to know that.
Once it does so, the new key is added to MyEntry's contents.
How can validate() discover the new keypress in order to validate it prior to addition to the Entry widget? Yikes!
Tkinter is a bit unfortunate in this situation, but Tk does provide what you are after so you can use it in Tkinter. You will have to change your: kwargs['vcmd']=self.validate to (after you call the __init__ method from Tk.Entry): kwargs['vcmd'] = (self.register(self.validate), '%P') # '%P' pass the possible new value for the entry, if it is validated or to: kwargs['vcmd'] = (self.register(self.validate), '%S') # '%S' will pass the text being inserted/deleted probably, based on what you described. There are some other substitutions that could be applied and combined if you are interested, they are all described in the entry widget manual in the tcl/tk site. Also, I believe if you use a textvariable with this entry then it will contain the new text when the validatecommand callback is invoked.
Thanks in advance, Jeff Cagle
_______________________________________________ Tkinter-discuss mailing list Tkinter-discuss@python.org http://mail.python.org/mailman/listinfo/tkinter-discuss
-- -- Guilherme H. Polo Goncalves
participants (2)
-
Guilherme Polo -
Jeff Cagle