如何选择与QDoubleValidator完全匹配的浮点数解析器?
问题根因
QDoubleValidator对千位分隔符的校验为宽松模式,仅判断字符是否为当前区域的合法千位分隔符,不会校验分隔符的分组位置是否合规,因此会放过8,0、8,0,0.0这类不符合en区域数字格式的输入;而QLocale::toDouble是严格匹配区域数字规则的,因此上述内容会解析失败。
解决方案
方案1:不需要支持千位分隔符输入(推荐,实现成本最低)
直接给你使用的QLocale("en")实例关闭千位分隔符识别,从根源避免逗号被误判为合法字符:
// C++ 示例 QLocale enLoc(QLocale::English, QLocale::UnitedStates); // 关闭千位分隔符识别 enLoc.setNumberOptions(QLocale::OmitGroupSeparator); QDoubleValidator *validator = new QDoubleValidator(bottom, top, decimals, this); validator->setLocale(enLoc); lineEdit->setValidator(validator);
# PyQt/PySide 示例 from PyQt6.QtCore import QLocale from PyQt6.QtGui import QDoubleValidator en_loc = QLocale(QLocale.Language.English, QLocale.Country.UnitedStates) en_loc.setNumberOptions(QLocale.NumberOption.OmitGroupSeparator) validator = QDoubleValidator(bottom, top, decimals, parent) validator.setLocale(en_loc) line_edit.setValidator(validator)
配置完成后,用同一个enLoc/en_loc实例调用toDouble方法即可100%解析校验通过的内容,不会出现解析失败的情况。
方案2:需要保留千位分隔符输入支持
如果业务需要允许用户输入带千位分隔符的数字,你需要自定义QDoubleValidator的子类,重写validate方法,在父类校验通过后提前做一次严格解析校验:
// C++ 自定义严格校验器示例 class StrictDoubleValidator : public QDoubleValidator { public: using QDoubleValidator::QDoubleValidator; QValidator::State validate(QString &input, int &pos) const override { QValidator::State state = QDoubleValidator::validate(input, pos); if (state == Acceptable) { bool parseOk = false; // 提前用绑定的locale做严格解析,只有解析成功才返回校验通过 locale().toDouble(input, &parseOk); if (!parseOk) { return Intermediate; } } return state; } };
使用这个自定义校验类替换原生QDoubleValidator即可,所有校验通过的输入都可以直接用同一个QLocale实例的toDouble方法解析成功。
关键注意点
- 不要使用Python内置的
float()函数解析带区域格式的数字,内置函数不识别区域相关的千位分隔符、小数点规则,必须用设置给校验器的同一个QLocale实例的toDouble方法解析。
内容的提问来源于stack exchange,提问作者Uroc327
相关产品推荐
相关产品推荐

