Qt中有Validator这个类,用来给QLineEdit之类的加入输入验证,原生的验证器有QIntValidator, QDoubleValidator, QRegExpValidator, QRegularExpressionValidator,分别对应着int,double,及正则,其中QRegularExpressionValidator是Qt5之后引入用以替代QRegExpValidator的,原因是QRegExpValidator中的东西过于老旧且bug不断。
下面是一个最简单的int型验证器的例子,通过如下代码设置过的LineEdit现在只能输入100到999这个范围内的整数,现在如果想在LineEdit中打汉字英文之类的,会发现完全输入不进去,没有反应。同理QDoubleValidator的用法也差不多。
QLineEdit *edit = new QLineEdit(this);
QValidator *validator = new QIntValidator(100, 999, this); //创建一个int验证器
edit->setValidator(validator); //给LineEdit设置验证器
大多数时候 QIntValidator和QDoubleValidator是不够用的,稍微复杂一点的输入验证就得上QRegularExpressionValidator了,下面是Qt官方的一个正则验证的例子。
// integers 1 to 9999
QRegularExpression re("[1-9]\\d{0,3}");
// the validator treats the regexp as "^[1-9]\\d{0,3}$"
QRegularExpressionValidator v(re, 0);
QString s;
int pos = 0;
s = "0"; v.validate(s, pos); // returns Invalid
s = "12345"; v.validate(s, pos); // returns Invalid
s = "1"; v.validate(s, pos); // returns Acceptable
re.setPattern("\\S+"); // one or more non-whitespace characters
v.setRegularExpression(re);
s = "myfile.txt"; v.validate(s, pos); // Returns Acceptable
s = "my file.txt"; v.validate(s, pos); // Returns Invalid
// A, B or C followed by exactly five digits followed by W, X, Y or Z
re.setPattern("[A-C]\\d{5}[W-Z]");
v.setRegularExpression(re);
s = "a12345Z"; v.validate(s, pos); // Returns Invalid
s = "A12345Z"; v.validate(s, pos); // Returns Acceptable
s = "B12"; v.validate(s, pos); // Returns Intermediate
// match most 'readme' files
re.setPattern("read\\S?me(\.(txt|asc|1st))?");
re.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
v.setRegularExpression(re);
s = "readme"; v.validate(s, pos); // Returns Acceptable
s = "README.1ST"; v.validate(s, pos); // Returns Acceptable
s = "read me.txt"; v.validate(s, pos); // Returns Invalid
s = "readm"; v.validate(s, pos); // Returns Intermediate
但是这些Qt自带的输入验证都有一些缺陷,比如QDoubleValidator设定的输入范围很多时候是无效的,可能是Qt的bug;而正则在面对一些小数或者复杂数的时候,表达式会非常长且很难写;另外还有一种很常见的场景,就是大多数大型软件的输入框不仅仅是可以输入数值的,并且能输入用户自定义的参数,比如用户自定了一个参数age=20,当在输入框输入age时,系统就会知道age实质上是值为10的int型。但是如果给这个输入框加入了IntValidator限制age的范围后,这个输入框便输入不了"age"这个参数了。
面对如上的问题,解决的方案一般是继承QValidator重写一个自定义的限制器,使之既能输入"age"这样的字符串,也能起到对数值范围限定验证的作用。同时提升QLineEdit重写一个加强版的QLineEdit,使之能够识别出"age"这样的全局参数,如果是"age",就把其对应的值10设定到LineEdit中,如果输入的仅仅是个数字,那就直接设定这个数字为值。
未完待续……