Why is Tkinter.StringVar () trying to get () to use its own value as an integer?
So, I have a slider that updates a record on change, and that record updates the slider on change. Basically they both represent the same value, but with two different input methods. The corresponding methods look like this (abbreviated):
class MyWindow(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack(fill=BOTH, expand=1)
self.makeWidgets()
def makeWidgets(self):
#controls to set the radius of a circle
#slider
self.radSlider = Scale(self, command=self.updateEntry)
self.radSlider.pack()
#entry
self.radVar = StringVar()
vcmd = (self.master.register(self.validateInt),
'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
self.radEntry = Entry(self,
validate = 'key',
validatecommand = vcmd,
textvariable=self.radVar)
self.radEntry.pack()
self.radVar.trace("w", self.updateSlide)
def updateEntry(self, *event):
rad = event[0]#first element of event is value of slider, as string
self.radVar.set(rad)
def updateSlide(self, *event):
if not self.radVar.get():#if entry is an empty string, set slider to zero
value = 0
else:
value = int(self.radVar.get())
self.radSlider.set(value)
def validateInt(self, action, index, value_if_allowed, prior_value, text, *args):
"""
validates an entry to integers and empty string only
"""
if (value_if_allowed == ""):
return True
if text in '0123456789':
try:
int(value_if_allowed)
return True
except:
return False
else:
return False
It works fine, but when radEntry is an empty string:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "C:\Users\ntopper\Desktop\Collector\NewObjDialog.py", line 127, in update Slide
if not self.radVar.get():
File "C:\Python27\lib\lib-tk\Tkinter.py", line 283, in get
return getint(self._tk.globalgetvar(self._name))
ValueError: invalid literal for int() with base 10: ''
One workaround is to never allow the entry to be an empty string, but having a zero that cannot be removed in the input window is a little pissed off. (to set the margin to 241, you first set the margin to 410, then 41, then 241)
Another option is to just ignore the error message because it doesn't break my program, but it's kind of sloppy.
It seems like Tkniter.StringVar (). get () is trying to pass its own string value as an integer, why is that?
source to share
Here is a simpler is_int (or empty) input validation element I just wrote for the Idle dialog.
# at module level
def is_int(s):
"Return is blank or represents an int'"
if not s:
return True
try:
int(s)
return True
except ValueError:
return False
...
# inside widget_subclass.__init__
self.is_int = self.register(is_int)
...
# inside widget_subclass method
Entry(entry_area, textvariable=var, validate='key',
validatecommand=(self.is_int, '%P')
).grid(row=row, column=1, sticky=NSEW, padx=7)
Regarding your error, when I fix the indentation in the validate dock like so:
def validateInt(self, action, index, value_if_allowed, prior_value, text, *args):
"""validates an entry to integers and empty string only"""
if value_if_allowed == "":
and working with 2.7.8 on Win7, your code works fine with no error message. Changing the slider or text will change the other as you intended.
Looking at my copy Python27\lib\lib-tk\Tkinter.py
,
return getint(self._tk.globalgetvar(self._name))
is on line 321 inside the method IntVar.get
where I expected it to be. Line 283, as in the trace above, is in the StringVar.__init__
docstring. Therefore, I assume that you are using an earlier version of 2.x and that your copy of Tkinter.py has a serious bug.
source to share