解决Tkinter Entry组件仅输整数且最多2字符的限制问题
问题:限制Tkinter Entry组件仅输入2位数字
- 需求:Entry组件最多输入2个字符,且仅接受数字输入
- 现状:已实现字符数限制,但无法限制仅输入数字;改用
IntVar()绑定后,字符数限制失效
当前代码
#Import TKinter module for GUI import tkinter as tk from tkinter import ttk from tkinter import font from tkinter import messagebox from tkinter import * #Create GUI Screen #Create Notebook GUI Widget root = Tk() note = ttk.Notebook(root) #------------------------------------------------------------------------------ def limit_size(*args): #Limit Entry Field to 2 Characters value1 = str(Rev_Maj_Value1.get()) if len(value1) >2:Rev_Maj_Value1.set(value1[:2]) def limit_size1(*args): value2 = str(Rev_Min_Value2.get()) if len(value2) >2:Rev_Min_Value2.set(value2[:2]) def limit_size2(*args): value3 = str(Rev_Maj_Value3.get()) if len(value3) >2:Rev_Maj_Value3.set(value3[:2]) def limit_size3(*args): value4 = str(Rev_Min_Value4.get()) if len(value4) >2:Rev_Min_Value4.set(value4[:2]) #------------------------------------------------------------------------------ Tab5 = ttk.Frame(note) canvas5 = Canvas(Tab5, width=550, height=350) canvas5.pack() #Entry Field Rev_Maj_Value1 = StringVar() Rev_Maj_Value1.trace('w', limit_size) Rev_Min_Value2 = StringVar() Rev_Min_Value2.trace('w', limit_size1) Rev_Maj_Value3 = StringVar() Rev_Maj_Value3.trace('w', limit_size2) Rev_Min_Value4 = StringVar() Rev_Min_Value4.trace('w', limit_size3) Rev_Maj1 = Entry(Tab5, justify="center", width=10, textvariable=Rev_Maj_Value1) Rev_Maj1.insert(0, "00") #Default Value Rev_Maj1__Window = canvas5.create_window(425, 175, anchor = 'sw', window = Rev_Maj1) Rev_Min2 = Entry(Tab5, justify="center", width=10, textvariable=Rev_Min_Value2) Rev_Min2.insert(0, "00") #Default Value Rev_Min2__Window = canvas5.create_window(425, 225, anchor = 'sw', window = Rev_Min2) Rev_Maj3 = Entry(Tab5, justify="center", width=10, textvariable=Rev_Maj_Value3) Rev_Maj3.insert(0, "00") #Default Value Rev_Maj3__Window = canvas5.create_window(425, 275, anchor = 'sw', window = Rev_Maj3) Rev_Min4 = Entry(Tab5, justify="center", width=10, textvariable=Rev_Min_Value4) Rev_Min4.insert(0, "00") #Default Value Rev_Min4__Window = canvas5.create_window(425, 325, anchor = 'sw', window = Rev_Min4) #------------------------------------------------------------------------------ #Create Notepad tabs note.add(Tab5, text = " 5 ") note.pack() #------------------------------------------------------------------------------ root.mainloop()
解决方案
方法1:改进现有trace函数,同时过滤非数字字符
原代码的trace函数仅限制长度,我们可以修改逻辑,同时过滤非数字字符,并合并重复函数减少冗余:
import tkinter as tk from tkinter import ttk from tkinter import font from tkinter import messagebox from tkinter import * root = Tk() note = ttk.Notebook(root) # 通用验证函数:过滤非数字+限制长度为2 def validate_and_limit(var, *args): value = var.get() # 只保留数字字符 filtered_value = ''.join([c for c in value if c.isdigit()]) # 限制长度最多2位 if len(filtered_value) > 2: filtered_value = filtered_value[:2] # 仅当处理后的值和原不同时设置,避免无限触发trace if filtered_value != value: var.set(filtered_value) Tab5 = ttk.Frame(note) canvas5 = Canvas(Tab5, width=550, height=350) canvas5.pack() # 初始化绑定变量并绑定通用验证函数 Rev_Maj_Value1 = StringVar(value="00") Rev_Maj_Value1.trace('w', lambda *args: validate_and_limit(Rev_Maj_Value1)) Rev_Min_Value2 = StringVar(value="00") Rev_Min_Value2.trace('w', lambda *args: validate_and_limit(Rev_Min_Value2)) Rev_Maj_Value3 = StringVar(value="00") Rev_Maj_Value3.trace('w', lambda *args: validate_and_limit(Rev_Maj_Value3)) Rev_Min_Value4 = StringVar(value="00") Rev_Min_Value4.trace('w', lambda *args: validate_and_limit(Rev_Min_Value4)) # 创建Entry组件 Rev_Maj1 = Entry(Tab5, justify="center", width=10, textvariable=Rev_Maj_Value1) Rev_Maj1__Window = canvas5.create_window(425, 175, anchor='sw', window=Rev_Maj1) Rev_Min2 = Entry(Tab5, justify="center", width=10, textvariable=Rev_Min_Value2) Rev_Min2__Window = canvas5.create_window(425, 225, anchor='sw', window=Rev_Min2) Rev_Maj3 = Entry(Tab5, justify="center", width=10, textvariable=Rev_Maj_Value3) Rev_Maj3__Window = canvas5.create_window(425, 275, anchor='sw', window=Rev_Maj3) Rev_Min4 = Entry(Tab5, justify="center", width=10, textvariable=Rev_Min_Value4) Rev_Min4__Window = canvas5.create_window(425, 325, anchor='sw', window=Rev_Min4) note.add(Tab5, text=" 5 ") note.pack() root.mainloop()
方法2:使用Tkinter官方推荐的validate验证机制
这种方法更高效,直接在Entry组件上设置输入验证,无需依赖StringVar的trace,能直接拦截非法输入:
import tkinter as tk from tkinter import ttk from tkinter import font from tkinter import messagebox from tkinter import * root = Tk() note = ttk.Notebook(root) # 输入验证函数:返回True表示允许输入,False表示拒绝 def validate_input(action, current_value, inserted_text): # action参数:0=删除操作,1=插入操作,2=获取当前值 if action == '1': # 插入字符时验证 # 检查插入的是否是数字,且当前长度未超过1(加上插入的字符后不超过2) if not inserted_text.isdigit() or len(current_value) >= 2: return False return True # 注册验证函数 vcmd = root.register(validate_input) Tab5 = ttk.Frame(note) canvas5 = Canvas(Tab5, width=550, height=350) canvas5.pack() # 创建带验证的Entry组件 Rev_Maj1 = Entry(Tab5, justify="center", width=10, validate="key", # 每次按键时触发验证 validatecommand=(vcmd, '%d', '%P', '%S')) # 传递验证所需参数 Rev_Maj1.insert(0, "00") Rev_Maj1__Window = canvas5.create_window(425, 175, anchor='sw', window=Rev_Maj1) Rev_Min2 = Entry(Tab5, justify="center", width=10, validate="key", validatecommand=(vcmd, '%d', '%P', '%S')) Rev_Min2.insert(0, "00") Rev_Min2__Window = canvas5.create_window(425, 225, anchor='sw', window=Rev_Min2) Rev_Maj3 = Entry(Tab5, justify="center", width=10, validate="key", validatecommand=(vcmd, '%d', '%P', '%S')) Rev_Maj3.insert(0, "00") Rev_Maj3__Window = canvas5.create_window(425, 275, anchor='sw', window=Rev_Maj3) Rev_Min4 = Entry(Tab5, justify="center", width=10, validate="key", validatecommand=(vcmd, '%d', '%P', '%S')) Rev_Min4.insert(0, "00") Rev_Min4__Window = canvas5.create_window(425, 325, anchor='sw', window=Rev_Min4) note.add(Tab5, text=" 5 ") note.pack() root.mainloop()
说明:
validate="key"表示每次按键输入时触发验证validatecommand中的%d是操作类型,%P是输入后的预期值,%S是插入的字符- 这种方法不会出现输入非法字符后再修正的闪烁问题
内容的提问来源于stack exchange,提问作者M.Tomlinson
相关产品推荐
相关产品推荐

