I'm trying to build a GUI that has many entry boxes, and these must be configurable to only accept integers AND only accept those integers that are <= a max value. I'm almost there, but my attempt exhibits odd behaviour. Any advice welcome. I posted this before, but it said this was answered; well, nothing I found did both of my requirements. Below is my attempt, but when I edit to try and make it accept only integers, it all goes wrong.
I've done this in Tcl/Tk, and it was quite easy, but I'm failing at every turn to get my Python version to do the same. :-(
This is the Tcl/Tk that works:
entry enMINS -textvar warm_mins -width 2 -validate all -vcmd {ValidIntRng %P 0 99}
##-----------------------------------------------------------------
proc ValidIntRng {val min max} {
expr {($val eq "") || ([string is integer $val] && ($val >= $min) && ($val <= $max))}
}
##-----------------------------------------------------------------
This is my Python which is not there yet: (Maybe a class is too ambitious for my current knowledge level, I just need a simple way to validate the Entry is an integer and <= to a max value ( >= min is not really needed, but be useful in future).
class EntryLen(tk.Entry):
def __init__(self, master=None, max_len=1, max_val=1, **kwargs):
self.var = tk.StringVar()
self.max_len = max_len
self.max_val = max_val
tk.Entry.__init__(self, master, textvariable=self.var, **kwargs)
self.old_value = ''
self.var.trace('w', self.check)
def check(self, *args):
if self.get().isint() and (len(self.get()) <= self.max_len) and (int(self.get()) <= self.max_val):
self.old_value = self.get() # accept change
else:
self.var.set(self.old_value) # reject change
You should use isdigital()
to check if the string represents an integer string, not isint()
as you do. Also empty string is a valid input for Tcl/Tk and you seems to not have a logic for that.
Here's your code corrected:
import tkinter as tk
class EntryLen(tk.Entry):
def __init__(self, master=None, max_len=1, max_val=1, **kwargs):
self.var = tk.StringVar()
self.max_len = max_len
self.max_val = max_val
tk.Entry.__init__(self, master, textvariable=self.var, **kwargs)
self.old_value = ''
self.var.trace('w', self.check)
def check(self, *args):
current_value = self.var.get()
if (current_value.isdigit() and
len(current_value) <= self.max_len and
int(current_value) <= self.max_val):
self.old_value = current_value
elif current_value == "":
self.old_value = current_value
else:
self.var.set(self.old_value)
root = tk.Tk()
entry_widget = EntryLen(root, max_len=2, max_val=99)
entry_widget.pack()
root.mainloop()