[英]Preventing the user from entering the same value twice using tkinter entry validation
我目前正在研究计算器程序。 我设法使验证代码起作用,因此条目小部件仅接收来自valid_input
列表的值。 虽然,我目前正在尝试阻止输入“ 5 ** 2”和“ 2 // 2”,但是有一种方法可以使用验证码或test_input
函数使用户无法输入两个相同的运算符。 这主要是关于除法和乘法运算符。
from tkinter import *
from tkinter import messagebox
def replace_text(text):
display.delete(0, END)
display.insert(0, text)
#Calculates the input in the display
def calculate(event = None):
equation = display.get()
try:
result = eval(equation)
replace_text(result)
print(result) #Just for reference
return True
except:
messagebox.showerror("Error", "Math Error", parent = root)
#This function dosen't allow the user to input invalid values
def test_input(value, action):
#list of inputs that is valid for the calculator to function
valid_input = ["7", "8", "9", "+", "4", "5", "6", "-", "1", "2", "3", "*", "0", ".", "/"]
if action == "1": #If an insertion is occuring in the entry
return all(char in valid_input for char in value)
# if action != 1, allow it
return True
root = Tk()
root.title("Calculator testing")
display = Entry(root, font=("Helvetica", 16), justify = "right", validate = "key")
display.configure(validatecommand = (display.register(test_input), "%S", "%d"))
display.insert(0, "")
display.grid(column = 0, row = 0, columnspan = 4, sticky = "NSWE", padx = 10, pady = 10)
display.bind("=", calculate)
#Equals button
button_equal = Button(root, font = ("Helvetica", 14), text = "=", command =
calculate, bg = "#c0ded9")
button_equal.grid(column = 2, row = 1, columnspan = 2, sticky = "WE")
#All clear button
button_clear = Button(root, font = ("Helvetica", 14), text = "AC", command =
lambda: replace_text(""), bg = "#c0ded9")
button_clear.grid(column = 0, row = 1, columnspan = 2, sticky = "WE")
#Main Program
root.mainloop()
在验证功能中,您可以拆分用于插入数字和插入运算符/点的逻辑。
由于您关心条目中已经存在的内容以及要插入字符的位置,因此应将更多信息传递给validatecommand
。 您需要的信息是( 来自此答案 ):
# %i = index of char string to be inserted/deleted, or -1
# %s = value of entry prior to editing
# %S = the text string being inserted or deleted, if any
然后,您可以进行几项检查,以禁止会插入两个运算符或一个接一个的运算符:
def test_input(insert, content, index, action):
#list of inputs that is valid for the calculator to function
valid_numbers = ["7", "8", "9", "4", "5", "6", "1", "2", "3", "0"]
valid_chars = ["+", "-", "*", ".", "/"]
index = int(index)
if action != "1": # Always allow if it's not an insert
return True
if insert in valid_numbers: # Always allow a number
return True
if insert in valid_chars: # If it's an operator or point do further checks
if index==0: # Disallow if it's the first character
return False
if content[index-1] in valid_chars: # Disallow if the character before is an operator or point
return False
if index != len(content): # If you're not at the end
if content[index] in valid_chars: # Disallow if the next character is an operator or point
return False
return True # Allow if it's none of the above
else:
return False # Disallow if the character is not a number, operator or point
同
display.configure(validatecommand = (display.register(test_input), "%S", "%s", "%i", "%d"))
我忘记了这会弄乱答案的插入,因为我假设一次只能插入一个字符。 您可以(至少)通过两种方式解决此问题:
您可以关闭用于插入答案的验证,并在插入后将其重新打开:
display.configure(validate='none')
display.insert(0, text)
display.configure(validate='key')
或者,因为答案总是所有的数字,你可以改变第二if
在验证命令允许多个号码,而不是只有一个:
if all(char in valid_numbers for char in insert):
您可以使用正则表达式来验证以下类型的字符串:
import re
_str = "3*42"
print(re.match(r'[0-9]+\.?[0-9]*[\+\-\*\/][0-9]+\.?[0-9]*', _str))
输出:
<_sre.SRE_Match对象; span =(0,4),match ='3 * 42'>
如您所见,如果RegEx匹配,则re.match
返回一个对象,否则返回None
。
有了这些信息,我们可以检查匹配是否返回一些信息来确定字符串是否有效:
import re
examples = ["3*42", # VALID
"3.14-42.0", # VALID
"12.0.0+21", # INVALID - 2 dots
"3--42", # INVALID - 2 operators
"3,14/42", # INVALID - comma instead of dot
"123 456", # INVALID - no operator
]
for operation in examples:
print("Operation {0} is: ".format(operation), end='')
if re.match(r'[0-9]+\.?[0-9]*[\+\-\*\/][0-9]+\.?[0-9]*', operation):
print("VALID")
else:
print("INVALID")
输出:
操作3 * 42为:有效
操作3.14-42.0为:有效
操作12.0.0 + 21为:无效
操作3--42为:无效
操作3,14 / 42是:INVALID
操作123456是:无效
RegEx的工作方式如下:
[0-9]+
:匹配一个或多个数字
\\.?
:匹配零个或一个点
[0-9]*
:匹配零个或多个数字
[\\+\\-\\*\\/]
:正好进入这四个符号之一( +-*/
)
[0-9]+
:匹配一个或多个数字
\\.?
:匹配零个或一个点
[0-9]*
:匹配零个或多个数字
如果我们把所有东西都放在一起,我们会要求:
一个或多个数字,后跟零个或一个点,然后是零个或多个数字,然后是运算符,然后是一个或多个数字,然后是零或一个点,然后是零个或多个数字
提示:您可以使用RegEx更改您的valid_input
:
r`[0-9\.\+\-\*\/]*`
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.