QSpinBox子类化一例(进制可变的SpinBox)

目的:创建一个进制可设置的spinbox。

类定义

子类化 QSpinBox 的关键就是实现下面的四个虚函数:

  • fixup()
  • validate()
  • textFromValue()
  • valueFromText()

除此之外,我们要设置采用的进制,所以添加一对函数

  • base()
  • setBase()

创建一个 private 的对象,存放私有变量

最终定义如下:

[cpp]  view plain copy
  1. #ifndef HBASESPINBOX_H  
  2. #define HBASESPINBOX_H  
  3. #include <QtGui/QSpinBox>  
  4. class HBaseSpinBoxPrivate;  
  5. class HBaseSpinBox : public QSpinBox  
  6. {  
  7.     Q_OBJECT  
  8. public:  
  9.     HBaseSpinBox(QWidget *parent = 0);  
  10.     ~HBaseSpinBox();  
  11.     virtual void fixup(QString& input) const;  
  12.     virtual QValidator::State validate(QString& input, int& pos) const;  
  13.     int base() const;  
  14.     void setBase(int b);  
  15. protected:  
  16.     virtual QString textFromValue(int value) const;  
  17.     virtual int valueFromText(const QString& text) const;  
  18. private:  
  19.     HBaseSpinBoxPrivate * d;  
  20. };  
  21. #endif // HBASESPINBOX_H  

类的实现文件

  • 先看一下 HBaseSpinBoxPrivate 的实现
    • 一个成员变量,存放当前采用的进制
    • 一个成员函数,用来校验和解析输入的字符串

[cpp]  view plain copy
  1. #include <QtCore/QDebug>  
  2. #include <QtCore/QStringBuilder>  
  3. #include <QtGui/QLineEdit>  
  4. #include "hbasespinbox.h"  
  5. class HBaseSpinBoxPrivate  
  6. {  
  7. public:  
  8.     HBaseSpinBoxPrivate(HBaseSpinBox *spinbox);  
  9.     int validateAndInterpret(QString &input, int &pos, QValidator::State &state);  
  10.     int base;  
  11.     HBaseSpinBox * p;  
  12. };  
  13. HBaseSpinBoxPrivate::HBaseSpinBoxPrivate(HBaseSpinBox *spinbox)  
  14.     :base(10), p(spinbox)  
  15. {}  
  16. int HBaseSpinBoxPrivate::validateAndInterpret(QString &input, int &pos, QValidator::State &state)  
  17. {  
  18.     QString copy = input;  
  19.     if (!p->prefix().isEmpty())  
  20.         copy = copy.mid(p->prefix().size());  
  21.     if (!p->suffix().isEmpty())  
  22.         copy.chop(p->suffix().size());  
  23.     const int max = p->maximum();  
  24.     const int min = p->minimum();  
  25.     state = QValidator::Acceptable;  
  26.     int num = min;  
  27.     if (!copy.size()) {  
  28.         //允许空输入  
  29.         state = QValidator::Intermediate;  
  30.     } else if (min<0 && copy[0]=='-'){  
  31.         state = QValidator::Intermediate;  
  32.     } else {  
  33.         bool ok = false;  
  34.         num = copy.toInt(&ok, base);  
  35.         if (!ok) {  
  36.             //转换失败,不可接受  
  37.             state = QValidator::Invalid;  
  38.         } else if (num >= min && num <= max) {  
  39.             //正常值  
  40.             state = copy == copy.toUpper()? QValidator::Acceptable : QValidator::Intermediate;  
  41.         } else if ((num >=0 && num > max) || (num < 0 && num < min)) {  
  42.             //数值越界且不可通过后续输入校正  
  43.             state = QValidator::Invalid;  
  44.         } else {  
  45.             state = QValidator::Intermediate;  
  46.         }  
  47.     }  
  48.     return num;  
  49. }  

类的实现就比较简单了:

[cpp]  view plain copy
  1. HBaseSpinBox::HBaseSpinBox(QWidget *parent)  
  2.     : QSpinBox(parent),d(new HBaseSpinBoxPrivate(this))  
  3. {  
  4. }  
  5. HBaseSpinBox::~HBaseSpinBox()  
  6. {  
  7.     delete d;  
  8. }  
  9. void HBaseSpinBox::fixup(QString &input) const  
  10. {  
  11.     QString copy = input;  
  12.     int pos = lineEdit()->cursorPosition();  
  13.     QValidator::State state;  
  14.     int num = d->validateAndInterpret(copy, pos, state);  
  15.     input = prefix() % QString::number(num, d->base).toUpper() % suffix();  
  16.     qDebug()<<input;  
  17. }  
  18. QValidator::State HBaseSpinBox::validate(QString& input, int& pos) const  
  19. {  
  20.     QValidator::State state;  
  21.     d->validateAndInterpret(input, pos, state);  
  22.     return state;  
  23. }  
  24. int HBaseSpinBox::base() const  
  25. {  
  26.     return d->base;  
  27. }  
  28. void HBaseSpinBox::setBase(int b)  
  29. {  
  30.     if (b<2 || b>36)  
  31.         qWarning("base must between 2 and 36");  
  32.     d->base = qBound(2, b, 36);  
  33. }  
  34. QString HBaseSpinBox::textFromValue(int value) const  
  35. {  
  36.     //不包括前缀和后缀  
  37.     return QString::number(value, d->base).toUpper();  
  38. }  
  39. int HBaseSpinBox::valueFromText(const QString& text) const  
  40. {  
  41.     QString copy = text;  
  42.     int pos = lineEdit()->cursorPosition();  
  43.     QValidator::State state;  
  44.     return d->validateAndInterpret(copy, pos, state);  
  45. }  

难点?

  • validate() 函数负责判断用户输入是否有效。
    • 如果数据完全符合条件,就是 QValidator::Acceptable
    • 如果数据肯定不可接受,就是 QValidator::Invalid
    • 如果数据是指部分符合,则返回 QValidator::Intermediate
      • 比如范围是 100~200,当前只输入了 10
      • 比如用户输入 00100,数值正确,但格式不好
      • 比如用户输入 +110,需要处理掉正号
  • fiixup() 最后的修正
    • 对于QValidator::Invalid 和 QValidator::Intermediate 的数据,可以在此进行一次修正。
  • 前缀和后缀的处理,需要搞清楚 validate和fixup中操作的都是包含前后缀的字符串。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值