QValidator для шестнадцатеричного входа

У меня есть спокойный виджет, который должен только принять шестнадцатеричную строку, как введено. Очень просто ограничить вводимые символы [0-9A-Fa-f], но я хотел бы иметь его дисплей с разделителем между "байтами" так, например, если разделитель является пространством и пользовательскими типами 0011223344 Я хотел бы, чтобы редактирование строки отобразилось 00 11 22 33 44 Теперь, если пользователь нажимает клавишу Backspace 3 раза, то я хочу, чтобы она отобразилась 00 11 22 3.

Я почти имею то, что я хочу, до сих пор существует только одно тонкое вовлечение ошибки с помощью клавиши Delete для удаления разделителя. У кого-либо есть лучший способ реализовать этот блок проверки допустимости? Вот мой код до сих пор:

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внутренний буфер, но я понятия не имею, где запустить с этого, и я воображаю, нетривиальное обязательство.

В сущности я хотел бы иметь Блок проверки допустимости, который соответствует этому regex: "[0-9A-Fa-f]( [0-9A-Fa-f])*" но я не хочу, чтобы пользователь когда-либо должен был ввести пространство как разделитель. Аналогично, при редактировании, что они вводят, пробелами нужно управлять неявно.

7
задан Evan Teran 3 May 2010 в 19:27
поделиться

2 ответа

Эван, попробуйте следующее:

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

inputMask позаботится о интервал, а «h» обозначает необязательный шестнадцатеричный символ («H» обозначает необязательный). Единственный недостаток: нужно заранее знать максимальную длину ввода. Мой пример выше позволяет использовать только четыре байта.

С уважением, Робин

6
ответ дан 7 December 2019 в 05:19
поделиться

Я предложу три подхода:

Вы можете повторно реализовать QLineEdit :: keyPressEvent () , чтобы по-разному обрабатывать обратную косую черту, когда символ слева от курсора QLineEdit находится пробел. Используя этот подход, вы также можете автоматически добавлять пробелы при вводе нового символа.

Другой подход - создать новый слот, связанный с сигналом QLineEdit :: textChanged () . Этот сигнал излучается при изменении текста. В этом слоте вы можете обрабатывать создание и удаление пространств в соответствии с вашими потребностями.

Наконец, вы можете создать новый класс, производный от QLineEdit , который повторно реализует метод QLineEdit :: paintEvent () . При таком подходе вы можете отображать пробелы между шестнадцатеричными словами, которые не хранятся в буфере QLineEdit .

1
ответ дан 7 December 2019 в 05:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: