2010-05-03 10 views
7

Ho un widget Qt che dovrebbe accettare solo una stringa esadecimale come input. È molto semplice limitare i caratteri di input a [0-9A-Fa-f], ma mi piacerebbe che fosse visualizzato con un delimitatore tra "byte", ad esempio se il delimitatore è uno spazio e l'utente digita 0011223344 Desidero visualizzare la riga 00 11 22 33 44 Ora se l'utente preme il tasto backspace 3 volte, allora voglio che visualizzi 00 11 22 3.QValidatore per ingresso esadecimale

I quasi avere quello che voglio, finora c'è solo un bug sottile che comporta l'utilizzo del tasto di cancellazione per rimuovere un delimitatore. Qualcuno ha un modo migliore per implementare questo validatore? Ecco il mio codice finora:

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

Per ora questo codice è abbastanza funzionale, ma mi piacerebbe farlo funzionare al 100% come previsto. Ovviamente l'ideale sarebbe semplicemente separare la visualizzazione della stringa esadecimale dai caratteri effettivi memorizzati nel buffer interno di QLineEdit ma non ho idea di dove cominciare e immagino sia un'impresa non banale.

In sostanza, mi piacerebbe avere un Validatore conforme a questa espressione regolare: "[0-9A-Fa-f]([0-9A-Fa-f])*" ma non voglio che l'utente debba mai digitare uno spazio come delimitatore. Allo stesso modo, quando si modifica ciò che tipizzano, gli spazi dovrebbero essere gestiti implicitamente.

risposta

1

proporrò tre approcci:

È possibile reimplementare il QLineEdit::keyPressEvent() per gestire backslash in modo diverso quando il personaggio appena lasciato al cursore s' il QLineEdit è uno spazio. Utilizzando questo approccio, puoi anche aggiungere automaticamente spazi quando viene digitato un nuovo carattere.

Un altro approccio consiste nel creare un nuovo slot, collegato al segnale QLineEdit::textChanged(). Questo segnale viene emesso quando il testo viene modificato. In questo slot, puoi gestire la creazione e la cancellazione di spazi in base alle tue esigenze.

Infine, è possibile creare una nuova classe, derivata da QLineEdit che reimplementa il metodo QLineEdit::paintEvent(). Con questo approccio, è possibile visualizzare lo spazio tra le parole esadecimali non memorizzate nel buffer QLineEdit.

+0

Credo che il terzo approccio è ottimale, ogni possibilità che avete visto esempi di tale codice? –

+0

Puoi guardare http://websvn.kde.org/trunk/KDE/kdeutils/okteta/parts/kbytesedit/, sembra essere rilevante (ma più complicato). – Lohrun

6

Evan, provate questo:

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

L'InputMask si occupa della spaziatura, e la "h" sta per un carattere esadecimale opzionale ("H" per un non-opzionale). Unico inconveniente: è necessario conoscere in anticipo la lunghezza massima di inserimento. Il mio esempio precedente consente solo quattro byte.

Con i migliori saluti, Robin

+0

Sì, ho pensato di usare anche quello. La lunghezza massima è comunque un problema. Vorrei poter ottenere l'effetto di quella maschera, ma essere in grado di dire che ripete: - /. –