8
votes

Qvalidator pour l'entrée hexagonale

J'ai un widget QT qui devrait seulement accepter une chaîne hexagonale en entrée. Il est très simple de limiter les caractères d'entrée à [0-9a-fa-f] code>, mais je voudrais le faire afficher avec un délimiteur entre "octets", donc par exemple si le délimiteur est un espace et les types d'utilisateurs 0011223344 CODE> Je voudrais que la ligne edit affiche 00 11 22 33 44 CODE> Si l'utilisateur appuie sur la touche BACKSPACE 3 fois, je le souhaite Affichage 00 11 22 3 Code>.

I PRESQUE STRUT> Ayez ce que je veux, jusqu'à présent, il n'y a qu'un bogue subtil impliquant à l'aide de la touche DELETE pour supprimer un délimiteur. Quelqu'un a-t-il un meilleur moyen de mettre en œuvre ce validateur? Voici mon code jusqu'à présent: P>

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;
    }
};


0 commentaires

3 Réponses :


1
votes

Je proposerai trois approches:

Vous pouvez réimplémenter le qlineDit :: keighpresserevent () pour gérer les barres arrière différemment lorsque le caractère vient de laisser au curseur qlineDit est un espace. En utilisant cette approche, vous pouvez également ajouter automatiquement des espaces lorsqu'un nouveau caractère est typé.

Une autre approche consiste à créer une nouvelle machine à sous, connectée au QLineDitIt :: textchanged () signal. Ce signal est émis lorsque le texte est modifié. Dans cet emplacement, vous pouvez gérer la création et la suppression des espaces en conséquence à vos besoins.

Enfin, vous pouvez créer une nouvelle classe, dérivée de QLineDit qui réinspire le QLineDitIt :: PaysEvent () méthode. Avec cette approche, vous pouvez afficher de l'espace entre vos mots hexagonaux qui ne sont pas stockés dans la mémoire tampon qLineDit.


2 commentaires

Je crois que la 3ème approche est optimale, toute chance que vous avez vu des exemples de ce code?


Vous pouvez regarder Webvn.kde.org/trunk/kde/kdeutils / okteta / parties / kbytesedit semble être pertinent (mais plus compliqué).



6
votes

Evan, essayez ceci:

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


1 commentaires

Oui, j'ai pensé à l'utiliser aussi. La durée maximale de la longueur est une question cependant. J'aimerais pouvoir avoir l'effet de ce masque, mais pouvoir dire qu'il répète: - /.



1
votes

La solution de Robin est bonne et fonctionne. Mais je pense que vous pouvez faire de mieux!
Utilisez ceci pour le masque d'entrée:

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


0 commentaires