| ValidateEntry |
UserPreferences |
| Tkinter Wiki | FrontPage | RecentChanges | TitleIndex | WordIndex | SiteNavigation | HelpContents | moin.sf.net |
The ValidateEntry widget, described on Fredrik Lundh's page on
Validating Entry Widget, can be used to confirm that the value that the user enters is what you, the programmer, wanted. Fredrik's example code doesn't show you how to retrieve the data entered by the user (use a ?StringVar called self.results), but the example below does. If you want to use the widget as a module that you import, you'll have to do a little more work.
Another approach to entry validation is provided in Chapter 6 of
Grayson's book on Tkinter. His example 6-17 spells out the details.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | '''
Info by Fredrik Lundh:
This module implements a validating version of the Tkinter Entry widget.
It uses the textvariable option to attach a StringVar to the widget,
and uses the variable trace function to keep track of what's going on (in real time, as the user types the input).
To specify how validation is to be done, override the validate method.
Note that the constructor takes a parent widget, and also allows you to use the value option to specify the initial contents.
All other options are passed on to the Entry widget itself.
'''
from Tkinter import *
class ValidatingEntry(Entry):
# base class for validating entry widgets
def __init__(self, master, value="", **kw):
apply(Entry.__init__, (self, master), kw)
self.__value = value
self.__variable = StringVar()
self.__variable.set(value)
self.__variable.trace("w", self.__callback)
self.config(textvariable=self.__variable)
self.results = StringVar()
if self.__value is None: self.results.set(None)
else:
self.results.set(self.__value)
def __callback(self, *dummy):
value = self.__variable.get()
newvalue = self.validate(value)
if newvalue is None:
self.__variable.set(self.__value)
elif newvalue != value:
self.__value = newvalue
self.__variable.set(newvalue)
else:
self.__value = value
def validate(self, value):
# override: return value, new value, or None if invalid
self.results.set(value)
return value
def getresults(self, value):
# override: return value, or chopped value in the case of ChopLengthEntry
return self.results.get()
'''
The first two examples are subclasses that check that the input is a valid Python integer or float, respectively.
The validate method simply tries to convert the value to an object of the right kind, and returns None (reject) if that fails.
'''
class IntegerEntry(ValidatingEntry):
def validate(self, value):
try:
if value:
v = int(value)
self.results.set(value)
return value
except ValueError:
return None
class FloatEntry(ValidatingEntry):
def validate(self, value):
try:
if value:
v = float(value)
self.results.set(value)
return value
except ValueError:
return None
class MaxLengthEntry(ValidatingEntry):
'''MaxLength is a subclass that restricts the length of the input to a given max length.
The getresults method is provided only to deal with a situation where a too-long
initial value is provided, and the user accepts it without editing.
Also if a too-long initial value is provided, it must be truncated to at least one char
less than the max length, or else the user will be unable to even edit it
(since the Del or BS key would cause the length to exceed the maxlength, they would be ignored)'''
def __init__(self, master, value="", maxlength=None, **kw):
if len(value) > maxlength-1:
value = value[:maxlength-1]
args = {'value': value}
self.maxlength = maxlength
apply(ValidatingEntry.__init__, (self, master), args)
def validate(self, value):
if self.maxlength is None or len(value) <= self.maxlength:
self.results.set(value)
return value
return None # new value too long
def getresults(self, value):
if self.maxlength:
if len(value) > self.maxlength:
value = value[:self.maxlength]
self.results.set(value)
return self.results.get()
class ChopLengthEntry(ValidatingEntry):
'''ChopLengthEntry accepts all entries, but chops them when the results are called for'''
def __init__(self, master, value="", maxlength=None, **kw):
args = {'value': value}
self.maxlength = maxlength
apply(ValidatingEntry.__init__, (self, master), args)
def getresults(self, value):
if self.maxlength:
if len(value) > self.maxlength:
value = value[:self.maxlength]
self.results.set(value)
return self.results.get()
class StringEntry(ValidatingEntry):
#same as ValidatingEntry; nothing extra
pass
if __name__ == '__main__':
labelString = ['Integer','Float','String','MaxLength','ChopLength']
limitString = ['MaxLength','ChopLength']
initial = [123, 456.789, '"hello, world!"', '"long text"', '"Please don\'t cut me!"']
num = len(labelString)
entry = []; value = []
for i in range(0,num):
entry.append(None)
value.append(None)
def results():
resultsList = []
for i in range(0,num):
value[i] = entry[i].results.get()
value[i] = entry[i].getresults(value[i])
if value[i] is not None:
resultsList.append( value[i] )
for i in range(len(resultsList)):
print "validated %s entry is: %s" % (labelString[i],resultsList[i] )
root.destroy()
root = Tk()
lab = []; but = []; entry = []
#if we put the names of the various widget into a list, we can create instances
# using a for loop. Note that we need to handle
# the special case that 2 of them have a 2nd argument, while the others don't
# (alternatively, could have re-defined the widgets to all take a (sometimes unneeded) 2nd argument)
for i in range(0, num):
lab.append(None); but.append(None); entry.append(None)
lab[i] = Label(text = 'please enter a '+labelString[i])
lab[i].pack(side='top')
txt = "%sEntry(root,value=%s)" % (labelString[i],str(initial[i]))
if labelString[i] in limitString:
maxLength = "10"
txt = "%sEntry(root,value=%s, maxlength=%s)" % (labelString[i],str(initial[i]),maxLength)
entry[i] = eval(txt)
entry[i].pack()
bt = Button(text = 'Ok', command = results)
bt.pack(side='left')
cn = Button(text = 'Cancel', command = root.destroy)
cn.pack(side='left')
mainloop() |
Screenshot: