Interactively validating Entry widget content in tkinter
What is the recommended technique for interactively validating content in a tkinter Entry
widget?
I've read the posts about using validate=True
and validatecommand=command
, and it appears that these features are limited by the fact that they get cleared if the validatecommand
command updates the Entry
widget's value.
Given this behavior, should we bind on the KeyPress
, Cut
, and Paste
events and monitor/update our Entry
widget's value through these events? (And other related events that I might have missed?)
Or should we forget interactive validation altogether and only validate on FocusOut
events?
python validation tkinter textbox
add a comment |
What is the recommended technique for interactively validating content in a tkinter Entry
widget?
I've read the posts about using validate=True
and validatecommand=command
, and it appears that these features are limited by the fact that they get cleared if the validatecommand
command updates the Entry
widget's value.
Given this behavior, should we bind on the KeyPress
, Cut
, and Paste
events and monitor/update our Entry
widget's value through these events? (And other related events that I might have missed?)
Or should we forget interactive validation altogether and only validate on FocusOut
events?
python validation tkinter textbox
add a comment |
What is the recommended technique for interactively validating content in a tkinter Entry
widget?
I've read the posts about using validate=True
and validatecommand=command
, and it appears that these features are limited by the fact that they get cleared if the validatecommand
command updates the Entry
widget's value.
Given this behavior, should we bind on the KeyPress
, Cut
, and Paste
events and monitor/update our Entry
widget's value through these events? (And other related events that I might have missed?)
Or should we forget interactive validation altogether and only validate on FocusOut
events?
python validation tkinter textbox
What is the recommended technique for interactively validating content in a tkinter Entry
widget?
I've read the posts about using validate=True
and validatecommand=command
, and it appears that these features are limited by the fact that they get cleared if the validatecommand
command updates the Entry
widget's value.
Given this behavior, should we bind on the KeyPress
, Cut
, and Paste
events and monitor/update our Entry
widget's value through these events? (And other related events that I might have missed?)
Or should we forget interactive validation altogether and only validate on FocusOut
events?
python validation tkinter textbox
python validation tkinter textbox
edited Aug 30 '17 at 13:33
Paolo Forgia
4,51262849
4,51262849
asked Nov 10 '10 at 1:24
MalcolmMalcolm
1,94243666
1,94243666
add a comment |
add a comment |
5 Answers
5
active
oldest
votes
The correct answer is, use the validatecommand
attribute of the widget. Unfortunately this feature is severely under-documented in the Tkinter world, though it is quite sufficiently documented in the Tk world. Even though it's not documented well, it has everything you need to do validation without resorting to bindings or tracing variables, or modifying the widget from within the validation procedure.
The trick is to know that you can have Tkinter pass in special values to your validate command. These values give you all the information you need to know to decide on whether the data is valid or not: the value prior to the edit, the value after the edit if the edit is valid, and several other bits of information. To use these, though, you need to do a little voodoo to get this information passed to your validate command.
Note: it's important that the validation command returns either True
or False
. Anything else will cause the validation to be turned off for the widget.
Here's an example that only allows lowercase (and prints all those funky values):
import tkinter as tk # python 3.x
# import Tkinter as tk # python 2.x
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
# valid percent substitutions (from the Tk entry man page)
# note: you only have to register the ones you need; this
# example registers them all for illustrative purposes
#
# %d = Type of action (1=insert, 0=delete, -1 for others)
# %i = index of char string to be inserted/deleted, or -1
# %P = value of the entry if the edit is allowed
# %s = value of entry prior to editing
# %S = the text string being inserted or deleted, if any
# %v = the type of validation that is currently set
# %V = the type of validation that triggered the callback
# (key, focusin, focusout, forced)
# %W = the tk name of the widget
vcmd = (self.register(self.onValidate),
'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
self.entry = tk.Entry(self, validate="key", validatecommand=vcmd)
self.text = tk.Text(self, height=10, width=40)
self.entry.pack(side="top", fill="x")
self.text.pack(side="bottom", fill="both", expand=True)
def onValidate(self, d, i, P, s, S, v, V, W):
self.text.delete("1.0", "end")
self.text.insert("end","OnValidate:n")
self.text.insert("end","d='%s'n" % d)
self.text.insert("end","i='%s'n" % i)
self.text.insert("end","P='%s'n" % P)
self.text.insert("end","s='%s'n" % s)
self.text.insert("end","S='%s'n" % S)
self.text.insert("end","v='%s'n" % v)
self.text.insert("end","V='%s'n" % V)
self.text.insert("end","W='%s'n" % W)
# Disallow anything but lowercase letters
if S == S.lower():
return True
else:
self.bell()
return False
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
12
This is the right way to do it. It addresses the problems I found when I tried to get jmeyer10's answer working. This one example provides superior documentation to validate compared to what I can find elsewhere. I wish I could give this 5 votes.
– Steven Rumbalski
Nov 10 '10 at 3:34
2
WOW! I agree with Steven - this is the type of reply that deserves more than one vote. You should write a book on Tkinter (and you've already posted enough solutions to make that a multi-volume series). Thank you!!!
– Malcolm
Nov 10 '10 at 13:31
As a side note: I'm blown away by the power of Tkinter. Its gotten a bad wrap for many years, but with the new support for native themes (ttk) and explanations of its hidden power powers by experts like Bryan Oakley, this GUI framework can hold its own against the likes of wxPython, pyQT, and others.
– Malcolm
Nov 10 '10 at 13:35
2
Thanks for the example. It's worth noting that the validatecommand MUST return a boolean (only True and False). If not, the validation will be removed.
– Dave Bacher
Jun 19 '12 at 5:50
2
I think this page should be brought to the fore.
– Right leg
Sep 8 '17 at 13:57
|
show 7 more comments
Use a Tkinter.StringVar
to track the value of the Entry widget. You can validate the value of the StringVar
by setting a trace
on it.
Here's a short working program that accepts only valid floats in the Entry widget.
from Tkinter import *
root = Tk()
sv = StringVar()
def validate_float(var):
new_value = var.get()
try:
new_value == '' or float(new_value)
validate.old_value = new_value
except:
var.set(validate.old_value)
validate.old_value = ''
# trace wants a callback with nearly useless parameters, fixing with lambda.
sv.trace('w', lambda nm, idx, mode, var=sv: validate_float(var))
ent = Entry(root, textvariable=sv)
ent.pack()
root.mainloop()
Thanks for your post. I enjoyed seeing the Tkinter StringVar .trace() method in use.
– Malcolm
Nov 10 '10 at 13:38
add a comment |
After studying and experimenting with Bryan's code, I produced a minimal version of input validation. The following code will put up an Entry box and only accept numeric digits.
from tkinter import *
root = Tk()
def testVal(inStr,acttyp):
if acttyp == '1': #insert
if not inStr.isdigit():
return False
return True
entry = Entry(root, validate="key")
entry['validatecommand'] = (entry.register(testVal),'%P','%d')
entry.pack()
root.mainloop()
Perhaps I should add that I am still learning Python and I will gladly accept any and all comments/suggestions.
Generally people useentry.configure(validatecommand=...)
and writetest_val
instead oftestVal
, but this is a good, simple example.
– wizzwizz4
Aug 12 '18 at 14:58
add a comment |
While studying Bryan Oakley's answer, something told me that a far more general solution could be developed. The following example introduces a mode enumeration, a type dictionary, and a setup function for validation purposes. See line 48 for example usage and a demonstration of its simplicity.
#! /usr/bin/env python3
# https://stackoverflow.com/questions/4140437
import enum
import inspect
import tkinter
from tkinter.constants import *
Mode = enum.Enum('Mode', 'none key focus focusin focusout all')
CAST = dict(d=int, i=int, P=str, s=str, S=str,
v=Mode.__getitem__, V=Mode.__getitem__, W=str)
def on_validate(widget, mode, validator):
# http://www.tcl.tk/man/tcl/TkCmd/ttk_entry.htm#M39
if mode not in Mode:
raise ValueError('mode not recognized')
parameters = inspect.signature(validator).parameters
if not set(parameters).issubset(CAST):
raise ValueError('validator arguments not recognized')
casts = tuple(map(CAST.__getitem__, parameters))
widget.configure(validate=mode.name, validatecommand=[widget.register(
lambda *args: bool(validator(*(cast(arg) for cast, arg in zip(
casts, args)))))]+['%' + parameter for parameter in parameters])
class Example(tkinter.Frame):
@classmethod
def main(cls):
tkinter.NoDefaultRoot()
root = tkinter.Tk()
root.title('Validation Example')
cls(root).grid(sticky=NSEW)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
def __init__(self, master, **kw):
super().__init__(master, **kw)
self.entry = tkinter.Entry(self)
self.text = tkinter.Text(self, height=15, width=50,
wrap=WORD, state=DISABLED)
self.entry.grid(row=0, column=0, sticky=NSEW)
self.text.grid(row=1, column=0, sticky=NSEW)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
on_validate(self.entry, Mode.key, self.validator)
def validator(self, d, i, P, s, S, v, V, W):
self.text['state'] = NORMAL
self.text.delete(1.0, END)
self.text.insert(END, 'd = {!r}ni = {!r}nP = {!r}ns = {!r}n'
'S = {!r}nv = {!r}nV = {!r}nW = {!r}'
.format(d, i, P, s, S, v, V, W))
self.text['state'] = DISABLED
return not S.isupper()
if __name__ == '__main__':
Example.main()
add a comment |
Bryan's answer is correct, however no one mentioned the 'invalidcommand' attribute of the tkinter widget.
A good explanation is here:
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html
Text copy/pasted in case of broken link
The Entry widget also supports an invalidcommand option that specifies a callback function that is called whenever the validatecommand returns False. This command may modify the text in the widget by using the .set() method on the widget's associated textvariable. Setting up this option works the same as setting up the validatecommand. You must use the .register() method to wrap your Python function; this method returns the name of the wrapped function as a string. Then you will pass as the value of the invalidcommand option either that string, or as the first element of a tuple containing substitution codes.
Note:
There is only one thing that I cannot figure out how to do: If you add validation to an entry, and the user selects a portion of the text and types a new value, there is no way to capture the original value and reset the entry. Here's an example
- Entry is designed to only accept integers by implementing 'validatecommand'
- User enters 1234567
- User selects '345' and presses 'j'. This is registered as two actions: deletion of '345', and insertion of 'j'. Tkinter ignores the deletion and acts only on the insertion of 'j'. 'validatecommand' returns False, and the values passed to the 'invalidcommand' function are as follows: %d=1, %i=2, %P=12j67, %s=1267, %S=j
- If the code does not implement an 'invalidcommand' function, the 'validatecommand' function will reject the 'j' and the result will be 1267. If the code does implement an 'invalidcommand' function, there is no way to recover the original 1234567.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f4140437%2finteractively-validating-entry-widget-content-in-tkinter%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
The correct answer is, use the validatecommand
attribute of the widget. Unfortunately this feature is severely under-documented in the Tkinter world, though it is quite sufficiently documented in the Tk world. Even though it's not documented well, it has everything you need to do validation without resorting to bindings or tracing variables, or modifying the widget from within the validation procedure.
The trick is to know that you can have Tkinter pass in special values to your validate command. These values give you all the information you need to know to decide on whether the data is valid or not: the value prior to the edit, the value after the edit if the edit is valid, and several other bits of information. To use these, though, you need to do a little voodoo to get this information passed to your validate command.
Note: it's important that the validation command returns either True
or False
. Anything else will cause the validation to be turned off for the widget.
Here's an example that only allows lowercase (and prints all those funky values):
import tkinter as tk # python 3.x
# import Tkinter as tk # python 2.x
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
# valid percent substitutions (from the Tk entry man page)
# note: you only have to register the ones you need; this
# example registers them all for illustrative purposes
#
# %d = Type of action (1=insert, 0=delete, -1 for others)
# %i = index of char string to be inserted/deleted, or -1
# %P = value of the entry if the edit is allowed
# %s = value of entry prior to editing
# %S = the text string being inserted or deleted, if any
# %v = the type of validation that is currently set
# %V = the type of validation that triggered the callback
# (key, focusin, focusout, forced)
# %W = the tk name of the widget
vcmd = (self.register(self.onValidate),
'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
self.entry = tk.Entry(self, validate="key", validatecommand=vcmd)
self.text = tk.Text(self, height=10, width=40)
self.entry.pack(side="top", fill="x")
self.text.pack(side="bottom", fill="both", expand=True)
def onValidate(self, d, i, P, s, S, v, V, W):
self.text.delete("1.0", "end")
self.text.insert("end","OnValidate:n")
self.text.insert("end","d='%s'n" % d)
self.text.insert("end","i='%s'n" % i)
self.text.insert("end","P='%s'n" % P)
self.text.insert("end","s='%s'n" % s)
self.text.insert("end","S='%s'n" % S)
self.text.insert("end","v='%s'n" % v)
self.text.insert("end","V='%s'n" % V)
self.text.insert("end","W='%s'n" % W)
# Disallow anything but lowercase letters
if S == S.lower():
return True
else:
self.bell()
return False
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
12
This is the right way to do it. It addresses the problems I found when I tried to get jmeyer10's answer working. This one example provides superior documentation to validate compared to what I can find elsewhere. I wish I could give this 5 votes.
– Steven Rumbalski
Nov 10 '10 at 3:34
2
WOW! I agree with Steven - this is the type of reply that deserves more than one vote. You should write a book on Tkinter (and you've already posted enough solutions to make that a multi-volume series). Thank you!!!
– Malcolm
Nov 10 '10 at 13:31
As a side note: I'm blown away by the power of Tkinter. Its gotten a bad wrap for many years, but with the new support for native themes (ttk) and explanations of its hidden power powers by experts like Bryan Oakley, this GUI framework can hold its own against the likes of wxPython, pyQT, and others.
– Malcolm
Nov 10 '10 at 13:35
2
Thanks for the example. It's worth noting that the validatecommand MUST return a boolean (only True and False). If not, the validation will be removed.
– Dave Bacher
Jun 19 '12 at 5:50
2
I think this page should be brought to the fore.
– Right leg
Sep 8 '17 at 13:57
|
show 7 more comments
The correct answer is, use the validatecommand
attribute of the widget. Unfortunately this feature is severely under-documented in the Tkinter world, though it is quite sufficiently documented in the Tk world. Even though it's not documented well, it has everything you need to do validation without resorting to bindings or tracing variables, or modifying the widget from within the validation procedure.
The trick is to know that you can have Tkinter pass in special values to your validate command. These values give you all the information you need to know to decide on whether the data is valid or not: the value prior to the edit, the value after the edit if the edit is valid, and several other bits of information. To use these, though, you need to do a little voodoo to get this information passed to your validate command.
Note: it's important that the validation command returns either True
or False
. Anything else will cause the validation to be turned off for the widget.
Here's an example that only allows lowercase (and prints all those funky values):
import tkinter as tk # python 3.x
# import Tkinter as tk # python 2.x
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
# valid percent substitutions (from the Tk entry man page)
# note: you only have to register the ones you need; this
# example registers them all for illustrative purposes
#
# %d = Type of action (1=insert, 0=delete, -1 for others)
# %i = index of char string to be inserted/deleted, or -1
# %P = value of the entry if the edit is allowed
# %s = value of entry prior to editing
# %S = the text string being inserted or deleted, if any
# %v = the type of validation that is currently set
# %V = the type of validation that triggered the callback
# (key, focusin, focusout, forced)
# %W = the tk name of the widget
vcmd = (self.register(self.onValidate),
'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
self.entry = tk.Entry(self, validate="key", validatecommand=vcmd)
self.text = tk.Text(self, height=10, width=40)
self.entry.pack(side="top", fill="x")
self.text.pack(side="bottom", fill="both", expand=True)
def onValidate(self, d, i, P, s, S, v, V, W):
self.text.delete("1.0", "end")
self.text.insert("end","OnValidate:n")
self.text.insert("end","d='%s'n" % d)
self.text.insert("end","i='%s'n" % i)
self.text.insert("end","P='%s'n" % P)
self.text.insert("end","s='%s'n" % s)
self.text.insert("end","S='%s'n" % S)
self.text.insert("end","v='%s'n" % v)
self.text.insert("end","V='%s'n" % V)
self.text.insert("end","W='%s'n" % W)
# Disallow anything but lowercase letters
if S == S.lower():
return True
else:
self.bell()
return False
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
12
This is the right way to do it. It addresses the problems I found when I tried to get jmeyer10's answer working. This one example provides superior documentation to validate compared to what I can find elsewhere. I wish I could give this 5 votes.
– Steven Rumbalski
Nov 10 '10 at 3:34
2
WOW! I agree with Steven - this is the type of reply that deserves more than one vote. You should write a book on Tkinter (and you've already posted enough solutions to make that a multi-volume series). Thank you!!!
– Malcolm
Nov 10 '10 at 13:31
As a side note: I'm blown away by the power of Tkinter. Its gotten a bad wrap for many years, but with the new support for native themes (ttk) and explanations of its hidden power powers by experts like Bryan Oakley, this GUI framework can hold its own against the likes of wxPython, pyQT, and others.
– Malcolm
Nov 10 '10 at 13:35
2
Thanks for the example. It's worth noting that the validatecommand MUST return a boolean (only True and False). If not, the validation will be removed.
– Dave Bacher
Jun 19 '12 at 5:50
2
I think this page should be brought to the fore.
– Right leg
Sep 8 '17 at 13:57
|
show 7 more comments
The correct answer is, use the validatecommand
attribute of the widget. Unfortunately this feature is severely under-documented in the Tkinter world, though it is quite sufficiently documented in the Tk world. Even though it's not documented well, it has everything you need to do validation without resorting to bindings or tracing variables, or modifying the widget from within the validation procedure.
The trick is to know that you can have Tkinter pass in special values to your validate command. These values give you all the information you need to know to decide on whether the data is valid or not: the value prior to the edit, the value after the edit if the edit is valid, and several other bits of information. To use these, though, you need to do a little voodoo to get this information passed to your validate command.
Note: it's important that the validation command returns either True
or False
. Anything else will cause the validation to be turned off for the widget.
Here's an example that only allows lowercase (and prints all those funky values):
import tkinter as tk # python 3.x
# import Tkinter as tk # python 2.x
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
# valid percent substitutions (from the Tk entry man page)
# note: you only have to register the ones you need; this
# example registers them all for illustrative purposes
#
# %d = Type of action (1=insert, 0=delete, -1 for others)
# %i = index of char string to be inserted/deleted, or -1
# %P = value of the entry if the edit is allowed
# %s = value of entry prior to editing
# %S = the text string being inserted or deleted, if any
# %v = the type of validation that is currently set
# %V = the type of validation that triggered the callback
# (key, focusin, focusout, forced)
# %W = the tk name of the widget
vcmd = (self.register(self.onValidate),
'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
self.entry = tk.Entry(self, validate="key", validatecommand=vcmd)
self.text = tk.Text(self, height=10, width=40)
self.entry.pack(side="top", fill="x")
self.text.pack(side="bottom", fill="both", expand=True)
def onValidate(self, d, i, P, s, S, v, V, W):
self.text.delete("1.0", "end")
self.text.insert("end","OnValidate:n")
self.text.insert("end","d='%s'n" % d)
self.text.insert("end","i='%s'n" % i)
self.text.insert("end","P='%s'n" % P)
self.text.insert("end","s='%s'n" % s)
self.text.insert("end","S='%s'n" % S)
self.text.insert("end","v='%s'n" % v)
self.text.insert("end","V='%s'n" % V)
self.text.insert("end","W='%s'n" % W)
# Disallow anything but lowercase letters
if S == S.lower():
return True
else:
self.bell()
return False
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
The correct answer is, use the validatecommand
attribute of the widget. Unfortunately this feature is severely under-documented in the Tkinter world, though it is quite sufficiently documented in the Tk world. Even though it's not documented well, it has everything you need to do validation without resorting to bindings or tracing variables, or modifying the widget from within the validation procedure.
The trick is to know that you can have Tkinter pass in special values to your validate command. These values give you all the information you need to know to decide on whether the data is valid or not: the value prior to the edit, the value after the edit if the edit is valid, and several other bits of information. To use these, though, you need to do a little voodoo to get this information passed to your validate command.
Note: it's important that the validation command returns either True
or False
. Anything else will cause the validation to be turned off for the widget.
Here's an example that only allows lowercase (and prints all those funky values):
import tkinter as tk # python 3.x
# import Tkinter as tk # python 2.x
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
# valid percent substitutions (from the Tk entry man page)
# note: you only have to register the ones you need; this
# example registers them all for illustrative purposes
#
# %d = Type of action (1=insert, 0=delete, -1 for others)
# %i = index of char string to be inserted/deleted, or -1
# %P = value of the entry if the edit is allowed
# %s = value of entry prior to editing
# %S = the text string being inserted or deleted, if any
# %v = the type of validation that is currently set
# %V = the type of validation that triggered the callback
# (key, focusin, focusout, forced)
# %W = the tk name of the widget
vcmd = (self.register(self.onValidate),
'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
self.entry = tk.Entry(self, validate="key", validatecommand=vcmd)
self.text = tk.Text(self, height=10, width=40)
self.entry.pack(side="top", fill="x")
self.text.pack(side="bottom", fill="both", expand=True)
def onValidate(self, d, i, P, s, S, v, V, W):
self.text.delete("1.0", "end")
self.text.insert("end","OnValidate:n")
self.text.insert("end","d='%s'n" % d)
self.text.insert("end","i='%s'n" % i)
self.text.insert("end","P='%s'n" % P)
self.text.insert("end","s='%s'n" % s)
self.text.insert("end","S='%s'n" % S)
self.text.insert("end","v='%s'n" % v)
self.text.insert("end","V='%s'n" % V)
self.text.insert("end","W='%s'n" % W)
# Disallow anything but lowercase letters
if S == S.lower():
return True
else:
self.bell()
return False
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
edited Jan 19 '17 at 13:09
answered Nov 10 '10 at 3:29
Bryan OakleyBryan Oakley
214k21255418
214k21255418
12
This is the right way to do it. It addresses the problems I found when I tried to get jmeyer10's answer working. This one example provides superior documentation to validate compared to what I can find elsewhere. I wish I could give this 5 votes.
– Steven Rumbalski
Nov 10 '10 at 3:34
2
WOW! I agree with Steven - this is the type of reply that deserves more than one vote. You should write a book on Tkinter (and you've already posted enough solutions to make that a multi-volume series). Thank you!!!
– Malcolm
Nov 10 '10 at 13:31
As a side note: I'm blown away by the power of Tkinter. Its gotten a bad wrap for many years, but with the new support for native themes (ttk) and explanations of its hidden power powers by experts like Bryan Oakley, this GUI framework can hold its own against the likes of wxPython, pyQT, and others.
– Malcolm
Nov 10 '10 at 13:35
2
Thanks for the example. It's worth noting that the validatecommand MUST return a boolean (only True and False). If not, the validation will be removed.
– Dave Bacher
Jun 19 '12 at 5:50
2
I think this page should be brought to the fore.
– Right leg
Sep 8 '17 at 13:57
|
show 7 more comments
12
This is the right way to do it. It addresses the problems I found when I tried to get jmeyer10's answer working. This one example provides superior documentation to validate compared to what I can find elsewhere. I wish I could give this 5 votes.
– Steven Rumbalski
Nov 10 '10 at 3:34
2
WOW! I agree with Steven - this is the type of reply that deserves more than one vote. You should write a book on Tkinter (and you've already posted enough solutions to make that a multi-volume series). Thank you!!!
– Malcolm
Nov 10 '10 at 13:31
As a side note: I'm blown away by the power of Tkinter. Its gotten a bad wrap for many years, but with the new support for native themes (ttk) and explanations of its hidden power powers by experts like Bryan Oakley, this GUI framework can hold its own against the likes of wxPython, pyQT, and others.
– Malcolm
Nov 10 '10 at 13:35
2
Thanks for the example. It's worth noting that the validatecommand MUST return a boolean (only True and False). If not, the validation will be removed.
– Dave Bacher
Jun 19 '12 at 5:50
2
I think this page should be brought to the fore.
– Right leg
Sep 8 '17 at 13:57
12
12
This is the right way to do it. It addresses the problems I found when I tried to get jmeyer10's answer working. This one example provides superior documentation to validate compared to what I can find elsewhere. I wish I could give this 5 votes.
– Steven Rumbalski
Nov 10 '10 at 3:34
This is the right way to do it. It addresses the problems I found when I tried to get jmeyer10's answer working. This one example provides superior documentation to validate compared to what I can find elsewhere. I wish I could give this 5 votes.
– Steven Rumbalski
Nov 10 '10 at 3:34
2
2
WOW! I agree with Steven - this is the type of reply that deserves more than one vote. You should write a book on Tkinter (and you've already posted enough solutions to make that a multi-volume series). Thank you!!!
– Malcolm
Nov 10 '10 at 13:31
WOW! I agree with Steven - this is the type of reply that deserves more than one vote. You should write a book on Tkinter (and you've already posted enough solutions to make that a multi-volume series). Thank you!!!
– Malcolm
Nov 10 '10 at 13:31
As a side note: I'm blown away by the power of Tkinter. Its gotten a bad wrap for many years, but with the new support for native themes (ttk) and explanations of its hidden power powers by experts like Bryan Oakley, this GUI framework can hold its own against the likes of wxPython, pyQT, and others.
– Malcolm
Nov 10 '10 at 13:35
As a side note: I'm blown away by the power of Tkinter. Its gotten a bad wrap for many years, but with the new support for native themes (ttk) and explanations of its hidden power powers by experts like Bryan Oakley, this GUI framework can hold its own against the likes of wxPython, pyQT, and others.
– Malcolm
Nov 10 '10 at 13:35
2
2
Thanks for the example. It's worth noting that the validatecommand MUST return a boolean (only True and False). If not, the validation will be removed.
– Dave Bacher
Jun 19 '12 at 5:50
Thanks for the example. It's worth noting that the validatecommand MUST return a boolean (only True and False). If not, the validation will be removed.
– Dave Bacher
Jun 19 '12 at 5:50
2
2
I think this page should be brought to the fore.
– Right leg
Sep 8 '17 at 13:57
I think this page should be brought to the fore.
– Right leg
Sep 8 '17 at 13:57
|
show 7 more comments
Use a Tkinter.StringVar
to track the value of the Entry widget. You can validate the value of the StringVar
by setting a trace
on it.
Here's a short working program that accepts only valid floats in the Entry widget.
from Tkinter import *
root = Tk()
sv = StringVar()
def validate_float(var):
new_value = var.get()
try:
new_value == '' or float(new_value)
validate.old_value = new_value
except:
var.set(validate.old_value)
validate.old_value = ''
# trace wants a callback with nearly useless parameters, fixing with lambda.
sv.trace('w', lambda nm, idx, mode, var=sv: validate_float(var))
ent = Entry(root, textvariable=sv)
ent.pack()
root.mainloop()
Thanks for your post. I enjoyed seeing the Tkinter StringVar .trace() method in use.
– Malcolm
Nov 10 '10 at 13:38
add a comment |
Use a Tkinter.StringVar
to track the value of the Entry widget. You can validate the value of the StringVar
by setting a trace
on it.
Here's a short working program that accepts only valid floats in the Entry widget.
from Tkinter import *
root = Tk()
sv = StringVar()
def validate_float(var):
new_value = var.get()
try:
new_value == '' or float(new_value)
validate.old_value = new_value
except:
var.set(validate.old_value)
validate.old_value = ''
# trace wants a callback with nearly useless parameters, fixing with lambda.
sv.trace('w', lambda nm, idx, mode, var=sv: validate_float(var))
ent = Entry(root, textvariable=sv)
ent.pack()
root.mainloop()
Thanks for your post. I enjoyed seeing the Tkinter StringVar .trace() method in use.
– Malcolm
Nov 10 '10 at 13:38
add a comment |
Use a Tkinter.StringVar
to track the value of the Entry widget. You can validate the value of the StringVar
by setting a trace
on it.
Here's a short working program that accepts only valid floats in the Entry widget.
from Tkinter import *
root = Tk()
sv = StringVar()
def validate_float(var):
new_value = var.get()
try:
new_value == '' or float(new_value)
validate.old_value = new_value
except:
var.set(validate.old_value)
validate.old_value = ''
# trace wants a callback with nearly useless parameters, fixing with lambda.
sv.trace('w', lambda nm, idx, mode, var=sv: validate_float(var))
ent = Entry(root, textvariable=sv)
ent.pack()
root.mainloop()
Use a Tkinter.StringVar
to track the value of the Entry widget. You can validate the value of the StringVar
by setting a trace
on it.
Here's a short working program that accepts only valid floats in the Entry widget.
from Tkinter import *
root = Tk()
sv = StringVar()
def validate_float(var):
new_value = var.get()
try:
new_value == '' or float(new_value)
validate.old_value = new_value
except:
var.set(validate.old_value)
validate.old_value = ''
# trace wants a callback with nearly useless parameters, fixing with lambda.
sv.trace('w', lambda nm, idx, mode, var=sv: validate_float(var))
ent = Entry(root, textvariable=sv)
ent.pack()
root.mainloop()
answered Nov 10 '10 at 2:47
Steven RumbalskiSteven Rumbalski
33.3k65893
33.3k65893
Thanks for your post. I enjoyed seeing the Tkinter StringVar .trace() method in use.
– Malcolm
Nov 10 '10 at 13:38
add a comment |
Thanks for your post. I enjoyed seeing the Tkinter StringVar .trace() method in use.
– Malcolm
Nov 10 '10 at 13:38
Thanks for your post. I enjoyed seeing the Tkinter StringVar .trace() method in use.
– Malcolm
Nov 10 '10 at 13:38
Thanks for your post. I enjoyed seeing the Tkinter StringVar .trace() method in use.
– Malcolm
Nov 10 '10 at 13:38
add a comment |
After studying and experimenting with Bryan's code, I produced a minimal version of input validation. The following code will put up an Entry box and only accept numeric digits.
from tkinter import *
root = Tk()
def testVal(inStr,acttyp):
if acttyp == '1': #insert
if not inStr.isdigit():
return False
return True
entry = Entry(root, validate="key")
entry['validatecommand'] = (entry.register(testVal),'%P','%d')
entry.pack()
root.mainloop()
Perhaps I should add that I am still learning Python and I will gladly accept any and all comments/suggestions.
Generally people useentry.configure(validatecommand=...)
and writetest_val
instead oftestVal
, but this is a good, simple example.
– wizzwizz4
Aug 12 '18 at 14:58
add a comment |
After studying and experimenting with Bryan's code, I produced a minimal version of input validation. The following code will put up an Entry box and only accept numeric digits.
from tkinter import *
root = Tk()
def testVal(inStr,acttyp):
if acttyp == '1': #insert
if not inStr.isdigit():
return False
return True
entry = Entry(root, validate="key")
entry['validatecommand'] = (entry.register(testVal),'%P','%d')
entry.pack()
root.mainloop()
Perhaps I should add that I am still learning Python and I will gladly accept any and all comments/suggestions.
Generally people useentry.configure(validatecommand=...)
and writetest_val
instead oftestVal
, but this is a good, simple example.
– wizzwizz4
Aug 12 '18 at 14:58
add a comment |
After studying and experimenting with Bryan's code, I produced a minimal version of input validation. The following code will put up an Entry box and only accept numeric digits.
from tkinter import *
root = Tk()
def testVal(inStr,acttyp):
if acttyp == '1': #insert
if not inStr.isdigit():
return False
return True
entry = Entry(root, validate="key")
entry['validatecommand'] = (entry.register(testVal),'%P','%d')
entry.pack()
root.mainloop()
Perhaps I should add that I am still learning Python and I will gladly accept any and all comments/suggestions.
After studying and experimenting with Bryan's code, I produced a minimal version of input validation. The following code will put up an Entry box and only accept numeric digits.
from tkinter import *
root = Tk()
def testVal(inStr,acttyp):
if acttyp == '1': #insert
if not inStr.isdigit():
return False
return True
entry = Entry(root, validate="key")
entry['validatecommand'] = (entry.register(testVal),'%P','%d')
entry.pack()
root.mainloop()
Perhaps I should add that I am still learning Python and I will gladly accept any and all comments/suggestions.
edited Jun 29 '18 at 0:56
JCKE
78110
78110
answered Feb 22 '16 at 13:16
user1683793user1683793
667613
667613
Generally people useentry.configure(validatecommand=...)
and writetest_val
instead oftestVal
, but this is a good, simple example.
– wizzwizz4
Aug 12 '18 at 14:58
add a comment |
Generally people useentry.configure(validatecommand=...)
and writetest_val
instead oftestVal
, but this is a good, simple example.
– wizzwizz4
Aug 12 '18 at 14:58
Generally people use
entry.configure(validatecommand=...)
and write test_val
instead of testVal
, but this is a good, simple example.– wizzwizz4
Aug 12 '18 at 14:58
Generally people use
entry.configure(validatecommand=...)
and write test_val
instead of testVal
, but this is a good, simple example.– wizzwizz4
Aug 12 '18 at 14:58
add a comment |
While studying Bryan Oakley's answer, something told me that a far more general solution could be developed. The following example introduces a mode enumeration, a type dictionary, and a setup function for validation purposes. See line 48 for example usage and a demonstration of its simplicity.
#! /usr/bin/env python3
# https://stackoverflow.com/questions/4140437
import enum
import inspect
import tkinter
from tkinter.constants import *
Mode = enum.Enum('Mode', 'none key focus focusin focusout all')
CAST = dict(d=int, i=int, P=str, s=str, S=str,
v=Mode.__getitem__, V=Mode.__getitem__, W=str)
def on_validate(widget, mode, validator):
# http://www.tcl.tk/man/tcl/TkCmd/ttk_entry.htm#M39
if mode not in Mode:
raise ValueError('mode not recognized')
parameters = inspect.signature(validator).parameters
if not set(parameters).issubset(CAST):
raise ValueError('validator arguments not recognized')
casts = tuple(map(CAST.__getitem__, parameters))
widget.configure(validate=mode.name, validatecommand=[widget.register(
lambda *args: bool(validator(*(cast(arg) for cast, arg in zip(
casts, args)))))]+['%' + parameter for parameter in parameters])
class Example(tkinter.Frame):
@classmethod
def main(cls):
tkinter.NoDefaultRoot()
root = tkinter.Tk()
root.title('Validation Example')
cls(root).grid(sticky=NSEW)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
def __init__(self, master, **kw):
super().__init__(master, **kw)
self.entry = tkinter.Entry(self)
self.text = tkinter.Text(self, height=15, width=50,
wrap=WORD, state=DISABLED)
self.entry.grid(row=0, column=0, sticky=NSEW)
self.text.grid(row=1, column=0, sticky=NSEW)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
on_validate(self.entry, Mode.key, self.validator)
def validator(self, d, i, P, s, S, v, V, W):
self.text['state'] = NORMAL
self.text.delete(1.0, END)
self.text.insert(END, 'd = {!r}ni = {!r}nP = {!r}ns = {!r}n'
'S = {!r}nv = {!r}nV = {!r}nW = {!r}'
.format(d, i, P, s, S, v, V, W))
self.text['state'] = DISABLED
return not S.isupper()
if __name__ == '__main__':
Example.main()
add a comment |
While studying Bryan Oakley's answer, something told me that a far more general solution could be developed. The following example introduces a mode enumeration, a type dictionary, and a setup function for validation purposes. See line 48 for example usage and a demonstration of its simplicity.
#! /usr/bin/env python3
# https://stackoverflow.com/questions/4140437
import enum
import inspect
import tkinter
from tkinter.constants import *
Mode = enum.Enum('Mode', 'none key focus focusin focusout all')
CAST = dict(d=int, i=int, P=str, s=str, S=str,
v=Mode.__getitem__, V=Mode.__getitem__, W=str)
def on_validate(widget, mode, validator):
# http://www.tcl.tk/man/tcl/TkCmd/ttk_entry.htm#M39
if mode not in Mode:
raise ValueError('mode not recognized')
parameters = inspect.signature(validator).parameters
if not set(parameters).issubset(CAST):
raise ValueError('validator arguments not recognized')
casts = tuple(map(CAST.__getitem__, parameters))
widget.configure(validate=mode.name, validatecommand=[widget.register(
lambda *args: bool(validator(*(cast(arg) for cast, arg in zip(
casts, args)))))]+['%' + parameter for parameter in parameters])
class Example(tkinter.Frame):
@classmethod
def main(cls):
tkinter.NoDefaultRoot()
root = tkinter.Tk()
root.title('Validation Example')
cls(root).grid(sticky=NSEW)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
def __init__(self, master, **kw):
super().__init__(master, **kw)
self.entry = tkinter.Entry(self)
self.text = tkinter.Text(self, height=15, width=50,
wrap=WORD, state=DISABLED)
self.entry.grid(row=0, column=0, sticky=NSEW)
self.text.grid(row=1, column=0, sticky=NSEW)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
on_validate(self.entry, Mode.key, self.validator)
def validator(self, d, i, P, s, S, v, V, W):
self.text['state'] = NORMAL
self.text.delete(1.0, END)
self.text.insert(END, 'd = {!r}ni = {!r}nP = {!r}ns = {!r}n'
'S = {!r}nv = {!r}nV = {!r}nW = {!r}'
.format(d, i, P, s, S, v, V, W))
self.text['state'] = DISABLED
return not S.isupper()
if __name__ == '__main__':
Example.main()
add a comment |
While studying Bryan Oakley's answer, something told me that a far more general solution could be developed. The following example introduces a mode enumeration, a type dictionary, and a setup function for validation purposes. See line 48 for example usage and a demonstration of its simplicity.
#! /usr/bin/env python3
# https://stackoverflow.com/questions/4140437
import enum
import inspect
import tkinter
from tkinter.constants import *
Mode = enum.Enum('Mode', 'none key focus focusin focusout all')
CAST = dict(d=int, i=int, P=str, s=str, S=str,
v=Mode.__getitem__, V=Mode.__getitem__, W=str)
def on_validate(widget, mode, validator):
# http://www.tcl.tk/man/tcl/TkCmd/ttk_entry.htm#M39
if mode not in Mode:
raise ValueError('mode not recognized')
parameters = inspect.signature(validator).parameters
if not set(parameters).issubset(CAST):
raise ValueError('validator arguments not recognized')
casts = tuple(map(CAST.__getitem__, parameters))
widget.configure(validate=mode.name, validatecommand=[widget.register(
lambda *args: bool(validator(*(cast(arg) for cast, arg in zip(
casts, args)))))]+['%' + parameter for parameter in parameters])
class Example(tkinter.Frame):
@classmethod
def main(cls):
tkinter.NoDefaultRoot()
root = tkinter.Tk()
root.title('Validation Example')
cls(root).grid(sticky=NSEW)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
def __init__(self, master, **kw):
super().__init__(master, **kw)
self.entry = tkinter.Entry(self)
self.text = tkinter.Text(self, height=15, width=50,
wrap=WORD, state=DISABLED)
self.entry.grid(row=0, column=0, sticky=NSEW)
self.text.grid(row=1, column=0, sticky=NSEW)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
on_validate(self.entry, Mode.key, self.validator)
def validator(self, d, i, P, s, S, v, V, W):
self.text['state'] = NORMAL
self.text.delete(1.0, END)
self.text.insert(END, 'd = {!r}ni = {!r}nP = {!r}ns = {!r}n'
'S = {!r}nv = {!r}nV = {!r}nW = {!r}'
.format(d, i, P, s, S, v, V, W))
self.text['state'] = DISABLED
return not S.isupper()
if __name__ == '__main__':
Example.main()
While studying Bryan Oakley's answer, something told me that a far more general solution could be developed. The following example introduces a mode enumeration, a type dictionary, and a setup function for validation purposes. See line 48 for example usage and a demonstration of its simplicity.
#! /usr/bin/env python3
# https://stackoverflow.com/questions/4140437
import enum
import inspect
import tkinter
from tkinter.constants import *
Mode = enum.Enum('Mode', 'none key focus focusin focusout all')
CAST = dict(d=int, i=int, P=str, s=str, S=str,
v=Mode.__getitem__, V=Mode.__getitem__, W=str)
def on_validate(widget, mode, validator):
# http://www.tcl.tk/man/tcl/TkCmd/ttk_entry.htm#M39
if mode not in Mode:
raise ValueError('mode not recognized')
parameters = inspect.signature(validator).parameters
if not set(parameters).issubset(CAST):
raise ValueError('validator arguments not recognized')
casts = tuple(map(CAST.__getitem__, parameters))
widget.configure(validate=mode.name, validatecommand=[widget.register(
lambda *args: bool(validator(*(cast(arg) for cast, arg in zip(
casts, args)))))]+['%' + parameter for parameter in parameters])
class Example(tkinter.Frame):
@classmethod
def main(cls):
tkinter.NoDefaultRoot()
root = tkinter.Tk()
root.title('Validation Example')
cls(root).grid(sticky=NSEW)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
def __init__(self, master, **kw):
super().__init__(master, **kw)
self.entry = tkinter.Entry(self)
self.text = tkinter.Text(self, height=15, width=50,
wrap=WORD, state=DISABLED)
self.entry.grid(row=0, column=0, sticky=NSEW)
self.text.grid(row=1, column=0, sticky=NSEW)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
on_validate(self.entry, Mode.key, self.validator)
def validator(self, d, i, P, s, S, v, V, W):
self.text['state'] = NORMAL
self.text.delete(1.0, END)
self.text.insert(END, 'd = {!r}ni = {!r}nP = {!r}ns = {!r}n'
'S = {!r}nv = {!r}nV = {!r}nW = {!r}'
.format(d, i, P, s, S, v, V, W))
self.text['state'] = DISABLED
return not S.isupper()
if __name__ == '__main__':
Example.main()
edited May 23 '17 at 12:02
Community♦
11
11
answered May 11 '16 at 20:06
Noctis SkytowerNoctis Skytower
13.6k115888
13.6k115888
add a comment |
add a comment |
Bryan's answer is correct, however no one mentioned the 'invalidcommand' attribute of the tkinter widget.
A good explanation is here:
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html
Text copy/pasted in case of broken link
The Entry widget also supports an invalidcommand option that specifies a callback function that is called whenever the validatecommand returns False. This command may modify the text in the widget by using the .set() method on the widget's associated textvariable. Setting up this option works the same as setting up the validatecommand. You must use the .register() method to wrap your Python function; this method returns the name of the wrapped function as a string. Then you will pass as the value of the invalidcommand option either that string, or as the first element of a tuple containing substitution codes.
Note:
There is only one thing that I cannot figure out how to do: If you add validation to an entry, and the user selects a portion of the text and types a new value, there is no way to capture the original value and reset the entry. Here's an example
- Entry is designed to only accept integers by implementing 'validatecommand'
- User enters 1234567
- User selects '345' and presses 'j'. This is registered as two actions: deletion of '345', and insertion of 'j'. Tkinter ignores the deletion and acts only on the insertion of 'j'. 'validatecommand' returns False, and the values passed to the 'invalidcommand' function are as follows: %d=1, %i=2, %P=12j67, %s=1267, %S=j
- If the code does not implement an 'invalidcommand' function, the 'validatecommand' function will reject the 'j' and the result will be 1267. If the code does implement an 'invalidcommand' function, there is no way to recover the original 1234567.
add a comment |
Bryan's answer is correct, however no one mentioned the 'invalidcommand' attribute of the tkinter widget.
A good explanation is here:
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html
Text copy/pasted in case of broken link
The Entry widget also supports an invalidcommand option that specifies a callback function that is called whenever the validatecommand returns False. This command may modify the text in the widget by using the .set() method on the widget's associated textvariable. Setting up this option works the same as setting up the validatecommand. You must use the .register() method to wrap your Python function; this method returns the name of the wrapped function as a string. Then you will pass as the value of the invalidcommand option either that string, or as the first element of a tuple containing substitution codes.
Note:
There is only one thing that I cannot figure out how to do: If you add validation to an entry, and the user selects a portion of the text and types a new value, there is no way to capture the original value and reset the entry. Here's an example
- Entry is designed to only accept integers by implementing 'validatecommand'
- User enters 1234567
- User selects '345' and presses 'j'. This is registered as two actions: deletion of '345', and insertion of 'j'. Tkinter ignores the deletion and acts only on the insertion of 'j'. 'validatecommand' returns False, and the values passed to the 'invalidcommand' function are as follows: %d=1, %i=2, %P=12j67, %s=1267, %S=j
- If the code does not implement an 'invalidcommand' function, the 'validatecommand' function will reject the 'j' and the result will be 1267. If the code does implement an 'invalidcommand' function, there is no way to recover the original 1234567.
add a comment |
Bryan's answer is correct, however no one mentioned the 'invalidcommand' attribute of the tkinter widget.
A good explanation is here:
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html
Text copy/pasted in case of broken link
The Entry widget also supports an invalidcommand option that specifies a callback function that is called whenever the validatecommand returns False. This command may modify the text in the widget by using the .set() method on the widget's associated textvariable. Setting up this option works the same as setting up the validatecommand. You must use the .register() method to wrap your Python function; this method returns the name of the wrapped function as a string. Then you will pass as the value of the invalidcommand option either that string, or as the first element of a tuple containing substitution codes.
Note:
There is only one thing that I cannot figure out how to do: If you add validation to an entry, and the user selects a portion of the text and types a new value, there is no way to capture the original value and reset the entry. Here's an example
- Entry is designed to only accept integers by implementing 'validatecommand'
- User enters 1234567
- User selects '345' and presses 'j'. This is registered as two actions: deletion of '345', and insertion of 'j'. Tkinter ignores the deletion and acts only on the insertion of 'j'. 'validatecommand' returns False, and the values passed to the 'invalidcommand' function are as follows: %d=1, %i=2, %P=12j67, %s=1267, %S=j
- If the code does not implement an 'invalidcommand' function, the 'validatecommand' function will reject the 'j' and the result will be 1267. If the code does implement an 'invalidcommand' function, there is no way to recover the original 1234567.
Bryan's answer is correct, however no one mentioned the 'invalidcommand' attribute of the tkinter widget.
A good explanation is here:
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html
Text copy/pasted in case of broken link
The Entry widget also supports an invalidcommand option that specifies a callback function that is called whenever the validatecommand returns False. This command may modify the text in the widget by using the .set() method on the widget's associated textvariable. Setting up this option works the same as setting up the validatecommand. You must use the .register() method to wrap your Python function; this method returns the name of the wrapped function as a string. Then you will pass as the value of the invalidcommand option either that string, or as the first element of a tuple containing substitution codes.
Note:
There is only one thing that I cannot figure out how to do: If you add validation to an entry, and the user selects a portion of the text and types a new value, there is no way to capture the original value and reset the entry. Here's an example
- Entry is designed to only accept integers by implementing 'validatecommand'
- User enters 1234567
- User selects '345' and presses 'j'. This is registered as two actions: deletion of '345', and insertion of 'j'. Tkinter ignores the deletion and acts only on the insertion of 'j'. 'validatecommand' returns False, and the values passed to the 'invalidcommand' function are as follows: %d=1, %i=2, %P=12j67, %s=1267, %S=j
- If the code does not implement an 'invalidcommand' function, the 'validatecommand' function will reject the 'j' and the result will be 1267. If the code does implement an 'invalidcommand' function, there is no way to recover the original 1234567.
edited Nov 20 '18 at 22:57
K.Dᴀᴠɪs
7,104112339
7,104112339
answered Nov 20 '18 at 22:39
orionrobertorionrobert
112
112
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f4140437%2finteractively-validating-entry-widget-content-in-tkinter%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown