Resident validating data entry

26-Nov-2019 14:18

This may lead to problems, for example, when the deletion should move the cursor to the left, while a substitution should move the cursor to the right.

Fortunately, these two processes are executed immediately after one another.

Tk() # creates a root window to place an entry with validation there def only_numeric_input(P): # checks if entry's value is an integer or empty and returns an appropriate boolean if P.isdigit() or P == "": # if a digit was entered or nothing was entered return True return False my_entry = tkinter.

June 30, 1998 | Fredrik Lundh This module implements a validating version of the Tkinter Entry widget.

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 import tkinter as tk # python 3.x # import Tkinter as tk # python 2.x class Example(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(Validate), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') self.entry = tk.

In this blog I will be sharing my personal best practices for data validation in the Power Apps that I design.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. Tk() def only_numeric_input(e): #this is allowing all numeric input if e.isdigit(): return True #this will allow backspace to work elif e=="": return True else: return False #this will make the entry widget on root window e1=tkinter.Entry(tk) #arranging entry widget on screen e1.grid(row=0,column=0) c=tk.register(only_numeric_input) e1.configure(validate="key",validatecommand=(c,'%P')) tk.mainloop() #very usefull for making app like calci Responding to orionrobert's problem of dealing with simple validation upon substitutions of text through selection, instead of separate deletions or insertions: A substitution of selected text is processed as a deletion followed by an insertion.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. 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. Text(self, height=15, width=50, wrap=WORD, state=DISABLED) self.entry.grid(row=0, column=0, sticky=NSEW) 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 delete(1.0, END) insert(END, 'd = \ni = \n P = \ns = \n' 'S = \nv = \n V = \n W = ' .format(d, i, P, s, S, v, V, W)) self.text['state'] = DISABLED return not S.isupper() if __name__ == '__main__': Example.main() Bryan's answer is correct, however no one mentioned the 'invalidcommand' attribute of the tkinter widget.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): # Cmd/ttk_entry.htm#M39 if mode not in Mode: raise Value Error('mode not recognized') parameters = inspect.signature(validator).parameters if not set(parameters).issubset(CAST): raise Value Error('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. A good explanation is here: 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.

In this blog I will be sharing my personal best practices for data validation in the Power Apps that I design.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. Tk() def only_numeric_input(e): #this is allowing all numeric input if e.isdigit(): return True #this will allow backspace to work elif e=="": return True else: return False #this will make the entry widget on root window e1=tkinter.Entry(tk) #arranging entry widget on screen e1.grid(row=0,column=0) c=tk.register(only_numeric_input) e1.configure(validate="key",validatecommand=(c,'%P')) tk.mainloop() #very usefull for making app like calci Responding to orionrobert's problem of dealing with simple validation upon substitutions of text through selection, instead of separate deletions or insertions: A substitution of selected text is processed as a deletion followed by an insertion.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. 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. Text(self, height=15, width=50, wrap=WORD, state=DISABLED) self.entry.grid(row=0, column=0, sticky=NSEW) 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 delete(1.0, END) insert(END, 'd = \ni = \n P = \ns = \n' 'S = \nv = \n V = \n W = ' .format(d, i, P, s, S, v, V, W)) self.text['state'] = DISABLED return not S.isupper() if __name__ == '__main__': Example.main() Bryan's answer is correct, however no one mentioned the 'invalidcommand' attribute of the tkinter widget.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): # Cmd/ttk_entry.htm#M39 if mode not in Mode: raise Value Error('mode not recognized') parameters = inspect.signature(validator).parameters if not set(parameters).issubset(CAST): raise Value Error('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. A good explanation is here: 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. Unfortunately this feature is severely under-documented in the Tkinter world, though it is quite sufficiently documented in the Tk world.