1

I have been surfing the web for answers that don't use the 'class' function but have not been very successful. What I've got is 3 entry boxes, for example, and I am trying to use this function (submitted by DorinPopescu) but instead of getting and setting a specific StringVar, I would like to possibly pass the relevant StringVar to the function and also pass the size of the entry.

I have tried this:

def limitSize(entry, max):
    max = int(max)
    value = entry.get()
    if len(value) > max: entry.set(value[:max])

UsernameVar= StringVar()
UsernameVar.trace('w', lambda: limitSize(UsernameVar, 10))
PasswordVar= StringVar()
PasswordVar.trace('w', lambda: limitSize(PasswordVar, 4))
AgeVar= StringVar()
AgeVar.trace('w', lambda: limitSize(AgeVar, 2))

Username=Entry(root, textvariable=UsernameVar).pack()
Password=Entry(root, textvariable=PasswordVar).pack()
Age=Entry(root, textvariable=AgeVar).pack()
jackdomleo7
  • 328
  • 3
  • 16
  • If you don't want to use `StringVar`, you can limit the size of the content of the entry using a `validatecommand` (http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html) – j_4321 Jan 18 '18 at 14:56
  • Your code is probably giving you an error, so you should add it to the question. Indeed, `trace` passes arguments to the callback (see https://stackoverflow.com/questions/29690463/what-are-the-arguments-to-tkinter-variable-trace-method-callbacks) while your lambda functions take no argument. You should do `lambda *args: limitSize(...)`. – j_4321 Jan 18 '18 at 15:00
  • Thanks! The '*args' worked perfectly! On the link in the question I noticed 'def limitSizeDay(*args):' but I didn't know if I needed it or where to put it in my code since I was already passing parameters. – jackdomleo7 Jan 18 '18 at 15:06

2 Answers2

1

The entry widget has options specifically for this sort of thing. You can set up a call back that will validate input, and reject any input that violates the constraints.

Here's a working example that limits the username to 10 characters, and password to 4:

import Tkinter as tk

def limitSize(new_value, max_len):
    return True if len(new_value) <= int(max_len) else False

root = tk.Tk()
_limitSize = root.register(limitSize)

username = tk.Entry(root, validate="key", validatecommand=(_limitSize, '%P', 10))
password = tk.Entry(root, validate="key", validatecommand=(_limitSize, '%P', 4))
username.pack(fill="x")
password.pack(fill="x")

root.mainloop()

The validate option specifies when the validation is done. "key" causes the validation to be done on every keypress. Other values are relatively self-explanatory: "none", "focus", "focusin", "focusout", or "all".

The validatecommand option specifies a tuple that requires a command that has been registered with the underlying tcl interpreter, and zero or more arguments. Tkinter has many special arguments that get replaced with information you can use to do the validation. In the above example, "%P" gets replaced with the value of the entry widget if the edit is allowed. You also have access to the type of edit (insert or delete), just the new text being inserted, and a few other things.

In this case we only care about the value if the edit is allowed. The callback is required to always return either True or False. If True is returned, the modification is allowed, and if False, the modification is disallowed.

One important thing to know: the values passed to the function will be converted to strings. That is why in the above example max_len is converted to an int before doing the comparison.

For a slightly more in-depth example, see this answer: https://stackoverflow.com/a/4140988/7432

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
0

Thanks to j_4321, please notice the '*args' that have been added to the lambda when calling the limitSize function in the StringVar traces.

def limitSize(entry, max):
    max = int(max)
    value = entry.get()
    if len(value) > max: entry.set(value[:max])

UsernameVar= StringVar()
UsernameVar.trace('w', lambda *args: limitSize(UsernameVar, 10))
PasswordVar= StringVar()
PasswordVar.trace('w', lambda *args: limitSize(PasswordVar, 4))
AgeVar= StringVar()
AgeVar.trace('w', lambda *args: limitSize(AgeVar, 2))

Username=Entry(root, textvariable=UsernameVar).pack()
Password=Entry(root, textvariable=PasswordVar).pack()
Age=Entry(root, textvariable=AgeVar).pack()
jackdomleo7
  • 328
  • 3
  • 16
  • By the way, if you use python3.6, `trace` is now deprecated (https://docs.python.org/3/whatsnew/3.6.html) and `trace_add` should be used instead (you will need to replace 'w' by 'write'). – j_4321 Jan 18 '18 at 15:15