[Tkinter-discuss] tkinter Entry validation: insert instead of replace
Doc Lans
codelans at gmail.com
Sat Feb 23 00:35:24 CET 2013
I removed your focus bind and all Entries work fine for me. I cannot insert
something incorrect and cannot leave Entries blank.
import Tkinter
class IntEntry(Tkinter.Entry):
def __init__(self, master=None, value=0, **kw):
Tkinter.Entry.__init__(self, master, **kw)
self._oldvalue = value
self.insert('end', value)
vcmd = (self.register(self._validate), '%s', '%P')
self.configure(validate='all', vcmd=vcmd)
self.bind('<FocusOut>', self._focus_out)
def _focus_out(self, event):
self.get()
def _validate(self, old, new):
if old != '':
self._oldvalue = old
if new == '':
return True
return new.isdigit()
def get(self):
value = Tkinter.Entry.get(self)
if value == '':
self.insert('end', self._oldvalue)
value = self._oldvalue
return int(value)
def set(self, value):
self.delete(0, 'end')
self.insert('end', value)
def printer():
for i in vals:
print i.get(),
print
root = Tkinter.Tk()
vals = []
for i in range(5):
e = IntEntry(root, value=(i + 1) * 111)
e.pack(side='top', padx=5, pady=5)
vals.append(e)
Tkinter.Button(text='print all', command=printer).pack(side='top')
root.mainloop()
2013/2/23 Michael Lange <klappnase at web.de>
> On Fri, 22 Feb 2013 21:59:50 +0600
> Teodor the Thinker <doctorlans at gmail.com> wrote:
>
> > Thank you. It was so simple! I changed function return to
> > return P.isdigit() or (P == "")
> > and it seems work.
> >
> > But it allows empty string not only during editing. I want to make:
> > when i clear the Entry and switch to another GUI element Entry
> > rollbacks to last valid value.
> >
> > But obvious code to achieve this goal doesnt work:
> > if P == "" and V == 'focusout':
> > return False
> > else:
> > return (P.isdigit() or P == "")
> >
> > I found when "return False" is executed, *s* variable is empty. So i
> > need to rollback not for last but to *before last* value. Is there a
> > nice bultin Tkinter way to achieve that or i should declare some
> > variable with "before last value" by my own?
>
> There is no (or at least I don't know of) any built-in way to do this.
>
> One possible way to work around this is to store the old value and restore
> it if required, as in this example:
>
> ##############################################################
> import Tkinter
>
> class IntEntry(Tkinter.Entry):
> def __init__(self, master=None, value=0, **kw):
> Tkinter.Entry.__init__(self, master, **kw)
> self._oldvalue = value
> self.insert('end', value)
> vcmd = (self.register(self._validate), '%s', '%P')
> self.configure(validate='all', vcmd=vcmd)
> self.bind('<FocusOut>', self._focus_out)
>
> def _focus_out(self, event):
> self.get()
>
> def _validate(self, old, new):
> if old != '':
> self._oldvalue = old
> if new == '':
> return True
> return new.isdigit()
>
> def get(self):
> value = Tkinter.Entry.get(self)
> if value == '':
> self.insert('end', self._oldvalue)
> value = self._oldvalue
> return int(value)
>
> def set(self, value):
> self.delete(0, 'end')
> self.insert('end', value)
>
> root = Tkinter.Tk()
> e1 = IntEntry(root, value=111)
> e1.pack(side='top', padx=100, pady=20)
> e2 = IntEntry(root, value=222)
> e2.pack(side='bottom', padx=100, pady=20)
> def test(event):
> print 'test'
> e2.bind('<FocusOut>', test)
> root.mainloop()
> ##############################################################
>
> This appears to work rather robust, it takes even care that get()
> will always return a decent value.
> However you see the weak point of this approach in the second Entry where
> a new binding to <FocusOut> events stops the validation from working
> properly.
> Using the "%V" substitution in the _validate() callback seems not to be
> exactly an alternative, because calling insert() from within the
> validation callback will again start validation and the results are hard
> to predict; sooner or later it may happen that Tk decides to turn off
> validation at all (at least I never managed to get such setups working).
>
> An alternative may (or may not ;) be to use the modified get() as above
> but to leave the empty Entries alone until some procedure is started by
> the user that calls get() which will automagically restore the last sane
> value (that's in fact what I did in one of my programs where I took the
> above example from).
>
> Regards
>
> Michael
>
> .-.. .. ...- . .-.. --- -. --. .- -. -.. .--. .-. --- ... .--. . .-.
>
> Another war ... must it always be so? How many comrades have we lost
> in this way? ... Obedience. Duty. Death, and more death ...
> -- Romulan Commander, "Balance of Terror", stardate 1709.2
> _______________________________________________
> Tkinter-discuss mailing list
> Tkinter-discuss at python.org
> http://mail.python.org/mailman/listinfo/tkinter-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tkinter-discuss/attachments/20130223/8828e807/attachment-0001.html>
More information about the Tkinter-discuss
mailing list