Tkinter entry validation: Check for a valid color or portion of a color

Question:

Recently, I have found that the validation option of Entry widgets is very useful (see this question). I recently tried to write a validation command that would verify that the user was typing a hex code, or a named color. I wrote this, and it works great for hex codes, and it sporadically works for colors. It runs on every keypress, among other things. (validate=ALL)

def checkColorValid(P):
    global backgroundColor
    if not P:
        return True

    if P.lower() in colors:
        backgroundColor = P
        return True

    if P[0] == '#':
        try:
            if len(P) == 1:
                return True
            int(P[1:], 16)
            if len(P) < 8:
                backgroundColor = P
                return True
            else:
                return False
        except ValueError:
            return False

    for color in colors:
        if color.startswith(P.lower()):
            return True

colors is a list of all valid named colors.
The validation code works, unless you are trying to type a named color, and start typing the same character over and over again. Once that happens, the validation appears to simply stop working. It no longer runs at all, until you restart the program.

Asked By: Balink

||

Answers:

It’s possible for the validation code to return None rather than True or False. Perhaps adding a final return statement will help.

Answered By: Bryan Oakley

Had the same problem and found this page in a search. Did not like it; but could not think of anything better. Then realized I was over-thinking it. Python has a great way to test anything for valid or not, ‘try’. Does not have to be bg; just whatever object is easy to use in whatever you a testing colors for.

def ColorTest(SomeColor):
    IsGood = True
    ColorTest=Toplevel()
    try:
        ColorTest['bg'] = SomeColor # Set backround color
        #print(SomeColor+' is a valid color')
        ColorTest.destroy()
        return IsGood
        
    except:
        #print(SomeColor+' is an invalid color')
        IsGood = False
        ColorTest.destroy()
        return IsGood
Answered By: Carl Mcgaha