1

我有一个数值范围为 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;
4

1 回答 1

2

您没有validatecommand正确使用该属性。该函数不应该直接改变值。该validatecommand函数的工作是返回TrueFalse。如果返回True则允许输入,否则将拒绝输入。

如果它返回除Trueor之外的任何其他内容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.

于 2021-02-22T05:23:15.563 回答