为什么验证不允许清除 "Entry" 字段?

Why validation does not allow clearing the "Entry" field?

编辑: 因此,问题是当您尝试在打开验证的情况下清除条目时,尽管调用了该函数,但它不会起作用,并且当您在验证函数开始时取消注释“return True”时它会起作用.

from tkinter import *
#Currying needed for callback function with args:
class curry:
    def __init__(self, fun, *args, **kwargs):
        self.fun = fun
        self.pending = args[:]
        self.kwargs = kwargs.copy(  )
    def __call__(self, *args, **kwargs):
        if kwargs and self.kwargs:
            kw = self.kwargs.copy(  )
            kw.update(kwargs)
        else:
            kw = kwargs or self.kwargs

        return self.fun(*(self.pending + args), **kw)

#Display is an tk.Entry child, with few functions as my own api
class Display(Entry):
    
    def __init__(self, root, column=0, row=0, args_grid={}, args_entry={}):
        super().__init__(root, **args_entry) 
        self.grid(column=column, row=row, **args_grid)

    def cleardisplay(self):
        print("deleting")
        self.delete(0,END)


def onclick(key,disp):
    if key=="clear":
        disp.cleardisplay()
        return

#list of all valid chars (when the validation schould return True)
VALIDCHARS=(1,2,3,4,5,6,7,8,9,0,"+","-","*","/","=")

def onValidate(validchars,char_to_validate,action):
    #return True                                        #when you uncomment this line, everything'll be fine
    if (char_to_validate in validchars): # or action==-1 or action==0:
        return True
    return False

#An actual program:
root = Tk()
vcmd=(root.register(onValidate),VALIDCHARS, '%S','%d')

args_entry={"width":40, "borderwidth":5,"validate":"key", "validatecommand":vcmd}
display = Display(root,0,0,args_entry=args_entry)

display.insert(0,"123")                         #notice, that it won't work with validation

buttonClear = Button(root,padx=40,pady=20,text="clear",command=curry(onclick,"clear",display)) 
buttonClear.grid(columnspan=3)
root.mainloop()

您的 onValidate 函数假设 char_to_validate 是单个字符。当您尝试插入“123”或尝试删除多个字符时,char_to_validate 将是一个字符串。当您插入“123”时,三字符字符串“123”不在有效字符列表中,因为有效字符列表是单个字符的列表。 “1”在列表中,“2”在列表中,“3”在列表中,但“123”不在列表中。

此外,由于如果条目为“123”并且您单击清除按钮,char_to_validate 将为“123”,您的验证将不起作用,因为它假设它仅在插入期间被调用单个字符而不是删除多个字符。如果您尝试删除“123”,您不想检查它们是否在有效字符列表中,您应该只在插入期间关心。

对于您的情况,我建议您传入 %P 而不是 %S,因为这会告诉您如果允许修改,字符串将是什么。然后您可以遍历字符串中的所有字符并验证每个字符都在有效字符列表中。

def onValidate(validchars,chars_to_validate,action):
    for char in chars_to_validate:
        if char not in validchars:
            # there is an invalid character in the input; don't allow it.
            return False
    return True
...
vcmd=(root.register(onValidate),VALIDCHARS, '%P','%d')

只要所有字符都在 validchars.

中,以上内容将不允许任何内容出现在条目中,或任何长度的字符串