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?

+3


source to share


1 answer


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.

+1


source







All Articles