I have a spinbox that has a values ranges from 0-366, it means it only allowed a numeric data type and a backspace. Whenever a user type a character, it automatically deleted if it not a number type. I'm from a C# background and this is my first attempt in Python language. Here is my code.
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)
From the code above, when I run it, it returns nothing. Since I'm from C# background. This is what I actually need. This is the C# keypress event
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;
You're not using the
validatecommandattribute properly. The function should never directly change the value. The job of thevalidatecommandfunction is to return eitherTrueorFalse. If it returnsTruethe input will be allowed, otherwise the input will be rejected.If it returns anything else besides
TrueorFalse(includingNone) or if the function attempts to change the value, the validation function will be disabled.You can configure tkinter to send the information you need to determine whether the data is valid or not. You should not be relying on the value returned by
get(), since that will only return the previous value rather than the value being input from the user.Since you're only wanting to allow integers, and you want to limit the value to a max of 366, the best solution would be to have tkinter pass in the value if the edit is allowed (using
%P), which you can then use to determine whether or not it is valid.You also should not bind to the
<Key>event, it's unnecessary for the validation to function, and in fact would get in the way of it working.The function would look something like this:
You should configure the
validatecommandlike the following (notice there's no space between%andP):You will probably need to add a little extra code elsewhere to handle the edge case where the user deletes everything in the widget and doesn't enter anything else. For example, you could use something like
value=sbDays.get() or 0.