概述
工作需要,需要对浮点数据进行验证修复,遂想到使用QDoubleSpinBox
,但自带的函数不足以满足我的需求,故自行子类化一个SpinBox
。
需求
- 设定默认值和范围,范围基于默认值;
- 设定梯度,如果超出范围或输入数据与默认数据的差不是梯度的整数倍则修正输入数据。
构思
QAbstractSpinBox
提供了4个虚函数,分别是fixup
,validate
,valueFromText
与textFromValue
;
fixup
:当validate
返回非QValidator::Acceptable
时调用。
validate
:输入时,将输入内容与当前位置作为入参,返回值有三个;
- QValidator::Invalid = 0:不合法;
- QValidator::Intermediate = 1:半合法;
- QValidator::Acceptable = 2: 合法;
valueFromText
:从字符串转换为值;
textFromValue
:从值转换为字符串。
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| class FollowStepSpinBox final : public QDoubleSpinBox { public: explicit FollowStepSpinBox(QWidget* parent = nullptr); ~FollowStepSpinBox(); void SetDefaultValue(double value, double range = 9999); protected: void fixup(QString &str) const override; QValidator::State validate(QString &input, int &pos) const override; double valueFromText(const QString& text) const override; QString textFromValue(double val) const override; private: double mDefaultValue; };
FollowStepSpinBox::FollowStepSpinBox(QWidget *parent) : QDoubleSpinBox(parent) , mDefaultValue(0) { setFixedSize(160, 40); }
FollowStepSpinBox::~FollowStepSpinBox() { }
void FollowStepSpinBox::SetDefaultValue(double value, double range) { setRange(value - fabs(range), value + fabs(range)); mDefaultValue = value; setValue(value); }
void FollowStepSpinBox::fixup(QString &str) { double value = valueFromText(str); value = mDefaultValue + round((value - mDefaultValue) / singleStep())*singleStep(); while(value > maximum()) { value -= singleStep(); } while(value < minmun()) { value += singleStpe(); } str = QString::number(value); }
QValidator::State FollowStepSpinBox::validate(QString &input, int &pos) const { static QRegExpValidator *validator = new QRegExpValidator(QRegExp("^[0-9\\.]*$")); if(validator->validate(input,pos) != QValidator::Acceptable) { return QValidator::Invalid; } const double value = valueFromText(input); const double times = fabs(value - mDefaultValue) / singleStep(); if(fabs(times - static_cast<int>(round(times)) < 1e-8) { return QValidator::Acceptable; } return QValidator::Invalid; }
double FollowStepSpinBox::valueFromText(const QString &text) const { return text.toDouble(); }
QString FollowStepSpinBox::textFromValue(double val) const { return QString::number(val); }
|