Reputation: 105
So I have a slider who updates an entry when changed, and that entry updates the slider when changed. Basically they both represent the same value but with two different methods of input. The relevant methods look like this (abridged):
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 can't be deleted in the entry box is mildly infuriating. (to set the box to 241, you would first set the box to 410, then 41, then 241)
The other option is just to ignore the error message because it does not crash my program, but that's sort of sloppy.
It seems that Tkniter.StringVar().get() is trying to cast it's own string value as an integer, why is this?
Upvotes: 3
Views: 547
Reputation: 19144
Here is the simpler is_int (or blank) Entry validator that I just wrote for an Idle dialog.
# at module level
def is_int(s):
"Return 's 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)
As for your error, when I fix the validate docstring indent 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 run with 2.7.8 on Win7, your code works fine with no error message. Changing either slider or text changes the other, as you designed.
Looking at my copy of Python27\lib\lib-tk\Tkinter.py
,
return getint(self._tk.globalgetvar(self._name))
is on line 321 inside the IntVar.get
method, where I expected it. Line 283, as in the traceback above, is in the StringVar.__init__
docstring. So my best guess is that you are running a earlier version of 2.x and that your copy of Tkinter.py has a severe bug.
Upvotes: 1