1

Related to an already answered question I have here, I still couldn't figure out how to solve the validation so that it doesn't break in ANY case. Currently, for the most part it's working nicely, except when you select the value and then type some input.

Example: load the program, select the number in the spinbox (8), then type any number. Even though the number is still within the range of control (1-128), it breaks validation with ValueError: invalid literal for int() with base 10: ''.

Any ideas, please?

try:
    from Tkinter import *
except ImportError:
    from tkinter import *

class GUI:
    def __init__(self):
        # root window of the whole program
        self.root = Tk()
        self.root.title('ImageSound')

        # registering validation command
        vldt_ifnum_cmd = (self.root.register(self.ValidateIfNum),'%P', '%S', '%W')

        # creating a spinbox
        harm_count = Spinbox(self.root, from_=1, to=128, width=5, justify='right', validate='all', validatecommand=vldt_ifnum_cmd)
        harm_count.insert(0,8)
        harm_count.delete(1,'end')
        harm_count.pack(padx=10, pady=10)

    def ValidateIfNum(self, user_input, new_value, widget_name):
        # disallow anything but numbers in the input
        valid = new_value == '' or new_value.isdigit()
        # now that we've ensured the input is only integers, range checking!
        if valid:
            # get minimum and maximum values of the widget to be validated
            minval = int(self.root.nametowidget(widget_name).config('from')[4])
            maxval = int(self.root.nametowidget(widget_name).config('to')[4])
            # check if it's in range
            if int(user_input) not in range (minval, maxval):
                valid = False
        if not valid:
            self.root.bell()
        return valid

if __name__ == '__main__':
    mainwindow = GUI()
    mainloop()
Community
  • 1
  • 1
Mario Krušelj
  • 653
  • 1
  • 6
  • 20

1 Answers1

1

The error says you are trying to convert an empty string to an integer. There's only one line of code where you're doing that, so the location of the error is pretty clear. You simply need to check for the empty string before attempting to convert user_input to an integer. That, or catch this specific error and return False, assuming an empty string is not valid.

Part of the root cause is due to the fact you have your parameters backwards. You pass in %P(new value) and %S (the text being inserted or deleted) in that order, yet your function has the parameters named user_input and new_value. Thus, %P is mapped to user_input and %S is mapped to new_value.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • Yep, I fixed the parameters being backwards. That was just an oversight on my part, oops. And yes, if I do one more check for '' before doing the len and in range checks, it works! Thank you, Bryan, you're a handful :) The user won't be able to select the whole number in the spinbox then type a new value (because that necessarily leaves the spinbox completely empty before the new character is placed there, which breaks validation)... but I don't think that's a big deal here. I'd rather have safe values at all times. – Mario Krušelj Aug 24 '15 at 20:27