DoubleValidator没有正确检查范围

Tar*_*rod 3 c++ qt qml qt5.4

让我用一个例子来解释这个问题。

如果有TextField这样的话

TextField {
    text: "0.0"
    validator: DoubleValidator { bottom: -359.9;
        top: 359.9;
        decimals: 1;
        notation: DoubleValidator.StandardNotation }

    onEditingFinished: {
        console.log("I'm here!");
    }                    
}
Run Code Online (Sandbox Code Playgroud)

我们可以键入数字,例如444.9399.9-555.5。如您所见,值不在-359.9和之间359.9

文档中,我们可以找到以下信息:

输入被接受,但如果输入的双精度数超出范围或格式错误,则该输入无效;例如,小数点后的位数过多或为空。

我以为DoubleValidator自己不接受这种事情,但是不幸的是它接受了。

因此,我想解决方案将是检查最终输入,但是我们又遇到一个问题:editingFinished仅当验证器返回可接受的状态时才会发出此消息,而情况并非总是如此。

也许我没有做一个好的方法,我不了解如何使用,DoubleValidator或者我需要一些C ++代码。

顺便说一句,我正在使用Qt 5.4。

x s*_*red 6

问题在于QML TextField接受中间输入:

验证者:验证者

允许您在TextField上设置验证器。设置验证器后,TextField 接受使text属性处于中间状态的输入。仅当按下Enter键时文本处于可接受的状态时,才会发送接受的信号。

validate()QDoubleValidator的功能全介绍,当它返回QValidator::Intermediate

状态QValidator :: validate(QString&input,int&pos)const

如果根据此验证器的规则输入无效,则此虚拟函数返回Invalid;如果可能再进行一些编辑将使输入可接受(例如,用户将“ 4”输入到接受10到99之间的整数的小部件中),则此虚拟函数返回Intermediate,如果输入有效,则接受。

因此,QValidator::Intermediate只要输入了双精度值,验证器将返回,并且由于TextField可以使用“ intermediate”,因此可以键入任何数字,只要它是数字即可。

您可以做的是子类化QDoubleValidator和重写validate(),以便Intermediate在值超出范围时它不会返回:

class TextFieldDoubleValidator : public QDoubleValidator {
public:
    TextFieldDoubleValidator (QObject * parent = 0) : QDoubleValidator(parent) {}
    TextFieldDoubleValidator (double bottom, double top, int decimals, QObject * parent) :
    QDoubleValidator(bottom, top, decimals, parent) {}

    QValidator::State validate(QString & s, int & pos) const {
        if (s.isEmpty() || (s.startsWith("-") && s.length() == 1)) {
            // allow empty field or standalone minus sign
            return QValidator::Intermediate;
        }
        // check length of decimal places
        QChar point = locale().decimalPoint();
        if(s.indexOf(point) != -1) {
            int lengthDecimals = s.length() - s.indexOf(point) - 1;
            if (lengthDecimals > decimals()) {
                return QValidator::Invalid;
            }
        }
        // check range of value
        bool isNumber;
        double value = locale().toDouble(s, &isNumber);
        if (isNumber && bottom() <= value && value <= top()) {
            return QValidator::Acceptable;
        }
        return QValidator::Invalid;
    }

};
Run Code Online (Sandbox Code Playgroud)