【问题标题】:QValidator for hex input用于十六进制输入的 QValidator
【发布时间】:2011-02-15 03:44:18
【问题描述】:

我有一个 Qt 小部件,它应该只接受一个十六进制字符串作为输入。将输入字符限制为[0-9A-Fa-f] 非常简单,但我想让它在“字节”之间显示一个定界符,例如,如果定界符是空格,并且用户键入0011223344 我想要行编辑以显示 00 11 22 33 44 现在如果用户按退格键 3 次,那么我希望它显示 00 11 22 3

几乎有我想要的,到目前为止只有一个微妙的错误涉及使用删除键删除分隔符。有没有人有更好的方法来实现这个验证器?到目前为止,这是我的代码:

class HexStringValidator : public QValidator {
public:
    HexStringValidator(QObject * parent) : QValidator(parent) {}

public:
    virtual void fixup(QString &input) const {
        QString temp;
        int index = 0;

            // every 2 digits insert a space if they didn't explicitly type one 
        Q_FOREACH(QChar ch, input) {
            if(std::isxdigit(ch.toAscii())) {

                if(index != 0 && (index & 1) == 0) {
                    temp += ' ';
                }

                temp += ch.toUpper();
                ++index;
            }
        }

        input = temp;
    }

    virtual State validate(QString &input, int &pos) const {
        if(!input.isEmpty()) {
            // TODO: can we detect if the char which was JUST deleted
            // (if any was deleted) was a space? and special case this?
            // as to not have the bug in this case?

            const int char_pos  = pos - input.left(pos).count(' ');
            int chars           = 0;
            fixup(input);

            pos = 0;

            while(chars != char_pos) {
                if(input[pos] != ' ') {
                    ++chars;
                }
                ++pos;
            }

            // favor the right side of a space
            if(input[pos] == ' ') {
                ++pos;
            }
        }
        return QValidator::Acceptable;
    }
};

目前,这段代码的功能已经足够了,但我希望它能够按预期 100% 工作。显然,理想的做法是将十六进制字符串的显示与存储在QLineEdit 的内部缓冲区中的实际字符分开,但我不知道从哪里开始,我想这是一项不平凡的工作。

本质上,我希望有一个符合这个正则表达式的验证器:"[0-9A-Fa-f]( [0-9A-Fa-f])*",但我不希望用户输入空格作为分隔符。同样,在编辑他们键入的内容时,应隐式管理空格。

【问题讨论】:

    标签: c++ qt qlineedit


    【解决方案1】:

    埃文,试试这个:

    QLineEdit * edt = new QLineEdit( this );  
    edt->setInputMask( "Hh hh hh hh" );
    

    inputMask 负责间距,“h”代表可选的十六进制字符(“H”代表非可选字符)。唯一的缺点:您必须提前知道最大输入长度。我上面的例子只允许四个字节。

    最好的问候, 罗宾

    【讨论】:

    • 是的,我也考虑过使用它。但是,最大长度是一个问题。我希望我能得到那个面具的效果,但可以说它重复:-/。
    【解决方案2】:

    我将提出三种方法:

    您可以重新实现QLineEdit::keyPressEvent() 以在刚刚离开QLineEdit 光标的字符是空格时以不同方式处理反斜杠。使用这种方法,您还可以在输入新字符时自动添加空格。

    另一种方法是创建一个新插槽,连接到QLineEdit::textChanged() 信号。当文本改变时发出这个信号。在此插槽中,您可以根据需要处理空间的创建和删除。

    最后,您可以创建一个派生自 QLineEdit 的新类,该类重新实现了 QLineEdit::paintEvent() 方法。使用这种方法,您可以在未存储在 QLineEdit 缓冲区中的十六进制单词之间显示空格。

    【讨论】:

    【解决方案3】:

    Robin 的解决方案很好并且有效。但我认为你可以做得最好!
    将此用于输入掩码:

    ui->lineEdit->setInputMask("HH-HH-HH-HH");
    

    在 ui 中,右击 lineEdit -> Go to Slots... -> textChanged。 在 slot 函数中写下这段代码:

    int c = ui->lineEdit->cursorPosition();
    ui->lineEdit->setText(arg1.toUpper());
    ui->lineEdit->setCursorPosition(c); // to not jump cursor's position
    

    现在您有了一个带有十六进制输入的 lineEdit,大写,带有破折号分隔符。

    有一段愉快的代码时间:)

    【讨论】:

      猜你喜欢
      • 2014-11-04
      • 1970-01-01
      • 2018-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多