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

2024-01-05 09:18

本文主要是介绍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中操作的都是包含前后缀的字符串。

这篇关于QSpinBox子类化一例(进制可变的SpinBox)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/572385

相关文章

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

usaco 1.2 Palindromic Squares(进制转化)

考察进制转化 注意一些细节就可以了 直接上代码: /*ID: who jayLANG: C++TASK: palsquare*/#include<stdio.h>int x[20],xlen,y[20],ylen,B;void change(int n){int m;m=n;xlen=0;while(m){x[++xlen]=m%B;m/=B;}m=n*n;ylen=0;whi

uva 10061 How many zero's and how many digits ?(不同进制阶乘末尾几个0)+poj 1401

题意是求在base进制下的 n!的结果有几位数,末尾有几个0。 想起刚开始的时候做的一道10进制下的n阶乘末尾有几个零,以及之前有做过的一道n阶乘的位数。 当时都是在10进制下的。 10进制下的做法是: 1. n阶位数:直接 lg(n!)就是得数的位数。 2. n阶末尾0的个数:由于2 * 5 将会在得数中以0的形式存在,所以计算2或者计算5,由于因子中出现5必然出现2,所以直接一

Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(4)

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正​​ Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(3)-CSDN博客  这节就是真正的存储数据了   理清一下思路: 1.存储路径并检查 //2进制文件类存储private static string Data_Binary_Pa

Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(3)

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正​​ Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(2) (*****生成数据结构类的方式特别有趣****)-CSDN博客 做完了数据结构类,该做一个存储类了,也就是生成一个字典类(只是声明)  实现和上一节的数据结构类的方式大同小异,所

itoa()函数,10进制转换到(2~36)进制

先看下itoa()的函数说明吧: 功 能:把一整数转换为字符串   用 法:char *itoa(int value, char *string, int radix);    详细解释:itoa是英文integer to array(将int整型数转化为一个字符串,并将值保存在数组string中)的缩写.    参数:  value: 待转化的整数。            radix:

Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(2) (*****生成数据结构类的方式特别有趣****)

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正​​ Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(1)-CSDN博客 本节内容 实现目标 通过已经得到的Excel表格数据,生成对应类对象(不赋值),一张表就是一个对象,其中包含了如下的字段  就像这样子  实现思路 上

C++11,可变参数模板,lambda表达式,包装器

可变参数模板 在C++11中模板也可以接收多个不定参数,就和int printf(const char *format, ...);函数一般模板也可以接收多个参数; // 可变参数模板template<class ...Args>void testArgs(Args... args){}int main(){testArgs(123, 'a', "abc",

[C/C++入门][进制原理]31、求分数序列和

题目来自于信息学奥赛 1078 分析: 这道题看起来比较复杂,实际上只需要通过两个公式,一次性求出分母和分子,然后把这个求出来的数加入到变量和中。甚至都不需要知道总共游哪些数。数组都用不上。循环就能解决。 #include <iostream>#include <iomanip> // 用于格式化输出using namespace std;int main() {double s

Java生成随机数工具类,进制之间的转换工具类,获取指定时间,时间格式转换工具类

废话不多说,贡献一下code 1.编号生成工具 import org.apache.commons.lang3.StringUtils;import java.math.BigInteger;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Random;/*** 编号生成工具*/@