【Qt】QLineEdit显示输入十六进制,位数不足时按照规则填充显示及每两个字符以空格填充

问题

在实际开发中,有时候需要对输入进行限制,一是更加合理,二是防止出现误操作。

比如:

使用Qt进行应用程序开发时,对单行编辑框QLineEdit控件,设置只可输入十六进制。

限制输入的方式常用且经典的是使用正则表达式。

示例1:设置QLineEdit输入十六进制:使用QRegExpValidator进行设置

设置QLineEdit只可输入十六进制,且为了不产生歧义,编辑框前两个字符为"0x"

包含头文件:

cpp 复制代码
#include <QRegExp>	// 正则表达式类
#include <QRegExpValidator> // 验证器

正则表达式:

cpp 复制代码
ui->lineEdit->setText("0x");
    ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("^0x[0-9a-f]+$
")));

^0x[0-9a-f]+$

是一个正则表达式,我们可以分步骤地解释它;至于没用到的就暂时不说,不然容易混淆视听:

  1. ^: 匹配字符串的开始。当此字符位于正则表达式的开始处时,它确保模式必须从字符串的开始处匹配。
  2. 0x: 这部分匹配字符串中的"0x"文字。
    [0-9a-f]: 这是一个字符集,它匹配任何一个在09或者af(小写)之间的字符。简单地说,它匹配任何一个十六进制字符。
  3. +: 表示前面的模式(在这里是[0-9a-f])可以出现一次或多次。
  4. $: 匹配字符串的结束。当此字符位于正则表达式的末尾时,它确保模式必须匹配到字符串的末尾。

因此,整个正则表达式^[0-9a-f]+$匹配的是:一个完全由十六进制字符组成的字符串。这意味着,如果一个字符串从开始到结束都是由十六进制字符组成的,那么这个正则表达式就会匹配成功。

所以,这个表达式,刚好符合咱们的需求。

为了防止误删,所以在QLineEditvoid textEdited(const QString &text)的槽函数内,添加

cpp 复制代码
    QString str = arg1;
    if(str.left(2).compare(QLatin1String("0x")) != 0)
    {
        str = QStringLiteral("0x");
        ui->lineEdit_4->setText(str);
    }

这样,确保编辑框前两位一直是"0x"。

示例2:设置QLineEdit输入十六进制:使用QRegularExpressionValidator进行设置

除了使用QRegExpValidator外,还可以使用QRegularExpressionValidator

而且,在Qt 5中,新的qregulareexpression类提供了正则表达式的Perl兼容实现,建议代替QRegExp

cpp 复制代码
    ui->lineEdit->setText("0x");
    ui->lineEdit->setValidator(new QRegularExpressionValidator(QRegularExpression("^0x[0-9a-f]+$")));

限制输入位数

如,限制只能输入3个十六进制位数

cpp 复制代码
ui->lineEdit->setText("0x");
    ui->lineEdit->setValidator(new QRegularExpressionValidator(QRegularExpression("^0x[0-9a-f]{1,3}$")));

^0x[0-9a-f]{1,3}$

  1. ^: 匹配字符串的开始。
  2. 0x: 这部分匹配字符串中的"0x"文字。
  3. [0-9a-f]: 这是一个字符集,它匹配任何一个在09或者af(小写)之间的字符。简单地说,它匹配任何一个十六进制字符。
  4. {1,3}: 这是一个数量修饰符,它表示前面的模式(在这里是[0-9a-f])可以出现1到3次。
  5. $: 匹配字符串的结束。

^0x[0-9a-f]{1,3}$的意思是:一个以"0x"开头并且其后紧跟1到3个十六进制字符的字符串。字符串以"0x"开始,并且从"0x"之后开始有1到3个十六进制字符,然后字符串结束,那么这个正则表达式就会匹配成功。例如,"0xa"、"0x12"和"0x123"都是与该正则表达式匹配的字符串,但"0x"或"0x1234"则不匹配。

当输入位数不足时,前面填充'0'

查询QString类帮助文档,发现有两个成员方法符合需求

1.inline QString QString::arg(int a, int fieldWidth, int base, QChar fillChar) const;

cpp 复制代码
    QString strArg = ui->lineEdit->text().trimmed();
    QString str = QString("%1").arg(strArg);

    str = QString("0x%1").arg(str.toInt(0, 16), 3, 16, QChar('0'));

    ui->lineEdit->setText(str);

如输入

cpp 复制代码
f

输出就是

cpp 复制代码
0x00f

2.QString rightJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const Q_REQUIRED_RESULT;

最后一个参数是如果truncate为false且字符串的size()大于width,则返回的字符串是该字符串的副本。

如果truncate为true并且字符串的size()大于width,则结果字符串将在位置width处被截断。

cpp 复制代码
    QString str = QString("%1%2%3%4%5%6%7%8%9").arg("a", "b", "c", "d", "e", "f", "g", "h", "i");
    bool bTrunc = false;
    str = str.rightJustified(10, QChar('0'), bTrunc);

输出就是

cpp 复制代码
0abcdefghi

除了以上两种方式外,哈可以自己判断进行填充。

cpp 复制代码
        QString str = "0xfe";
        if(str.toInt(0, 16) < 0x10)
        {
            str = QString("0x00%1").arg(QString::number(str.toInt(0, 16), 16));
        }else if(str.toInt(0, 16) < 0x100){
            str = QString("0x0%1").arg(QString::number(str.toInt(0, 16), 16));
        }else if(str.toInt(0, 16) < 0x1000){
            str = QString("0x%1").arg(QString::number(str.toInt(0, 16), 16));
        }

        qDebug().noquote() << "str :" << str; // "0x0fe"

每两位字符以空格隔开

当十六进制输入位数多时,如abcdefg这样,会显示拥挤,没有ab cd ef g看起来整洁。

如何让每两个字符以空格隔开呢?

提供以下4中方式:

方式1:进行位数判断,每次都取两位进行空格填充
cpp 复制代码
    QString strArg = ui->lineEdit->text().trimmed();
    // 填充
    QString str = QString("0x%1").arg(strArg.toInt(0, 16), 3, 16, QChar('0'));

    // 如:0xaabbccdde  输出: 0x aa bb cc dd e
    QString strSour = str;
    // 替换掉空格
    strSour = strSour.replace(" ", "");
    QString strRes = "";    // 结果

    int strLen = strSour.count();
    if(strSour.left(2).compare(QLatin1String("0x")) == 0)
    {
        if(strLen > 2)
        {
            // 判断奇偶
            if(0 == strLen%2)
            {
                // 取最后2位之前的子串
                for(int i = 0; i < strLen/2-1; ++i)
                {
                    QString strTmp = strSour.mid(i*2, 2);
                    strRes += strTmp + " ";
                }
                // 加上的子串
                strRes += strSour.right(2);
            }else{
                // 取最后1位之前的子串
                for(int i = 0; i <= strLen/2-1; ++i)
                {
                    QString strTmp = strSour.mid(i*2, 2);
                    strRes += strTmp + " ";
                }
                // 加上的子串
                strRes += strSour.right(1); // 加上最后的一位
            }
            ui->lineEdit->setText(strRes);
        }
    }else{
        // send error
        
    }
方式2:优化方法一

去掉奇偶判断,只判断最后一位或者两位,代码立刻优雅起来。

cpp 复制代码
    QString strArg = ui->lineEdit->text().trimmed();
    // 填充
    QString str = QString("0x%1").arg(strArg.toInt(0, 16), 3, 16, QChar('0'));

    // 如:0xaabbccdde  输出: 0x aa bb cc dd e
    QString strSour = str;
    // 替换掉空格
    strSour = strSour.replace(" ", "");
    QString strRes = "";    // 结果

    int strLen = strSour.count();
    if(strSour.left(2).compare(QLatin1String("0x")) == 0)
    {
        if(strLen > 2)
        {
            for(int i = 0; i < strLen/2-1; i++)
            {
                QString strTmp = strSour.mid(i*2, 2);
                strRes += strTmp + " ";
            }
            // 根据奇偶,加上最后的1或者2位
            strRes += strSour.right(strLen%2 == 0 ? 2 : 1);

            ui->lineEdit->setText(strRes);
        }
    }else{
        // send error

    }
方式3:使用while循环
cpp 复制代码
    QString strArg = ui->lineEdit->text().trimmed(); // aabbc
    // 填充
    QString str = QString("0x%1").arg(strArg.toInt(0, 16), 3, 16, QChar('0')); // 0xaabbc
    str = str.replace(" ", "");
    int nLen = str.length();
    int nIndex = 0;
    while( 2*(nIndex+1) < nLen )
    {
        str.insert(2*(nIndex+1), " ");
        ++nIndex;
    }
    ui->lineEdit->setText(str); // 0x aa bb c
方式4:使用正则表达式,推荐
cpp 复制代码
    QString strArg = ui->lineEdit->text().trimmed();
    // 填充
    QString str = QString("0x%1").arg(strArg.toInt(0, 16), 3, 16, QChar('0'));
    str = str.replace(" ", ""); // 0xaabbccdde
    QRegExp regex("(.{2})"); // 正则表达式,匹配任意两个字符

    // 使用正则表达式进行替换操作,将匹配到的两个字符之间添加空格
    QString result = str.replace(regex, "\\1 ");

    ui->lineEdit->setText(result); // 0x aa bb cc dd e

结论

一个人如果没有梦想,跟无忧无虑有什么区别

相关推荐
用户805533698033 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner3 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz8 天前
QML Hello World 入门示例
qt
xcyxiner11 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner12 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner12 天前
DicomViewer (添加模型类)3
qt
xcyxiner13 天前
DicomViewer (目录调整) 2
qt
xcyxiner13 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00615 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术15 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript