问题描述
我有一个数值范围为 0-366 的旋转框,这意味着它只允许数字数据类型和退格。每当用户键入一个字符时,如果它不是数字类型,它就会自动删除。我来自 C# 背景,这是我第一次尝试使用 Python 语言。这是我的代码。
def validate(event):
charPress=event.keysym
val=sbDays.get() #prevIoUs values
if not charPress.isdigit():
sbDays.config(textvariable=StringVar(windows).set(val))
sbDays=tk.SpinBox(frame,from_=0,to=366,borderwidth=sbBorderWidth)
sbDays.place(relx=initialX,rely=ydistance,relwidth=sbWidth)
sbDays.config(validate='all',validatecommand=(windows.register(validate),'% P'))
sbDays.update()
sbDays.bind('<Key>',validate)
从上面的代码来看,当我运行它时,它什么都不返回。因为我来自 C# 背景。这才是我真正需要的。这是 C# 按键事件
public static void TextBox_KeyPress_NumberBackspace(object sender,KeyPressEventArgs e)
{
char keyChar = e.KeyChar;
if (char.IsNumber(keyChar) || char.IsControl(keyChar))
e.Handled = false;
else
e.Handled = true;
}
tbDays.KeyPress += TextBox_KeyPress_NumberBackspace;
解决方法
您没有正确使用 validatecommand
属性。该函数不应直接更改该值。 validatecommand
函数的工作是返回 True
或 False
。如果返回 True
则允许输入,否则拒绝输入。
如果它返回除 True
或 False
(包括 None
)之外的任何其他内容,或者如果该函数尝试更改该值,则验证功能将被禁用。
你可以配置tkinter发送你需要的信息来判断数据是否有效。您不应依赖 get()
返回的值,因为它只会返回先前的值,而不是用户输入的值。
由于您只想允许整数,并且您希望将该值限制为最大 366,因此最好的解决方案是在允许编辑的情况下让 tkinter 传入该值(使用 %P
),然后您可以使用它来确定它是否有效。
您也不应该绑定到 <Key>
事件,它没有必要让验证起作用,而且实际上会妨碍它的工作。
函数看起来像这样:
def validate(new_value):
if new_value == "":
# allow blank entry so user doesn't get frustrated
# when trying to delete the first character
return True
try:
value = int(float(new_value))
except ValueError:
return False
return value >= 0 and value <= 366
您应该像下面这样配置 validatecommand
(注意 %
和 P
之间没有空格):
sbDays.configure(validate='all',validatecommand=(root.register(validate),'%P'))
您可能需要在其他地方添加一些额外的代码来处理用户删除小部件中的所有内容并且不输入任何其他内容的极端情况。例如,您可以使用 value=sbDays.get() or 0
之类的内容。