QIntValidator verbunden mit QLineEdit, Status abfragen

Alles rund um die Programmierung mit Qt
Antworten
Spinoza
Beiträge: 23
Registriert: 4. März 2011 01:07

QIntValidator verbunden mit QLineEdit, Status abfragen

Beitrag von Spinoza »

Hallo zusammen,
nachdem ich mit C++ lediglich für HPCs und damit Konsolenprogramme programmiert habe, möchte ich nun anfangen auch für meinen Desktop zuhause Anwendungen zu schreiben. Also mache ich mich gerade fit in Qt.

Eine Verwirrung, auf die ich gestoßen bin:
Ich habe ein QLineEdit ("HourEd") verbunden mit einem QIntValidator, sodass nur Ganzzahlen akzeptiert werden. Diese Verbindung schaffe ich im Konstruktor des Hauptfensters:

Code: Alles auswählen

QIntValidator *intvalidator = new QIntValidator(this);
ui->HourEd->setValidator(intvalidator);
Bei jeder Änderung im QLineEdit möchte ich nun einen anderen Wert aktualisieren, der vom Inhalt des LineEdits abhängt. Davor muss ich aber natürlich prüfen, ob dieser auch gültig ist (d.h. nicht nur QValidator::Intermediate (z.B. leerer string), sondern QValidator::Acceptable)
Wie prüfe ich nun diese Gültigkeit?
Ich suche nach einer art "HourEd->validator()->Status == QValidator::Acceptable"

Hier erstmal der Code, wie ich ihn momentan im textChanged-Event von HourEd habe:

Code: Alles auswählen

void MainWindow::on_HourEd_textChanged(QString )
{
  QString str = ui->HourEd->text();
  int dummyint;
  if (ui->HourEd->validator()->validate(str, dummyint) == QValidator::Acceptable)
  {
    /* Hier anderen Wert aktualisieren */
  }
}
Wie man sieht, ist das etwas um die Ecke programmiert. Ich mache pro Tastendruck nochmal extra eine validation mit dem Text in HourEd. Wenn der QIntValidator aber doch schon mit HourEd verbunden ist, muss es doch eine Möglichkeit geben, seinen aktuellen Status einfach abzufragen, ohne nochmal eine zusätzliche Prüfung vorzunehmen? Für mich wirkt das so, als würde ich QIntValidator nicht richtig benutzen, bzw. zu umständlich.
Vielleicht kann mich ja jemand aufklären :)

MfG
Spinoza

PS Die Möglichkeit mit der SpinBox ist mir bekannt, aber ich will ja Qt bzw. hier den Umgang mit QValidator lernen :)
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag von padreigh »

du benutzt das falsche Signal - deines wird ausgelöst sobald sich der Text ändert, du suchst eines, das nur ausgelöst wird wenn der Text Valide ist und sich änderte. (editing finished Hint Hint) Wenn du einen Slot daran hängst, dann wird der nur aufgerufen wenn was richtiges drin ist.

Alternativ kannst du die Eingabe auch nur auf beliebige Anzahl Zahlen einschränken (setInputMask("....")); oder bei der jetzigen bleiben, per QRegExp den Inhalt überprüfen und dort bei Eingabe von etwas anderem als Zahlen die Eingabe mit lineEdit.undo() rückgängig machen (und hoff das keiner 3.14e14 eingeben will - oder deine Regexp das frisst ;) ) - damit klaust du jedes falsch eingegebene Zeichen sofort wieder --- viele Möglichkeiten
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
Spinoza
Beiträge: 23
Registriert: 4. März 2011 01:07

Beitrag von Spinoza »

padreigh hat geschrieben:du suchst eines, das nur ausgelöst wird wenn der Text Valide ist und sich änderte. (editing finished Hint Hint) Wenn du einen Slot daran hängst, dann wird der nur aufgerufen wenn was richtiges drin ist.
Hm, daran hatte ich auch schon gedacht, aber das Signal editingFinished wird doch nur ausgelöst, wenn Return gedrückt wird oder das LineEdit den Fokus verliert. Ich möchte aber ja eine "live" aktualisierung während des Tippens haben, und nicht erst, wenn die Eingabe z.B. durch Klick in ein anderes Feld beendet wurde.
Ein weiteres Problem das dadurch entstehen würde: Ich bekomme nicht mit, wenn was ungültiges eingegeben wurde um z.B. den Wert als ungültig zu markieren :|.

Was mir noch eingefallen ist, ist eine neue QValidator-Klasse von QIntValidator abzuleiten, welche immer die letzte Prüfung in einem Klassenfeld nach aussen anbietet, aber das erscheint mir etwas overkill für so ein banales feature ne extra Klasse zu schreiben. Kann doch nicht sein, dass die sonst so bedachten Qt-Macher sowas vergessen haben? Das besiegt ja fast den Sinn einen Validator mit einem Edit zu verbinden, wenn ich den Status nicht abfragen kann.
padreigh hat geschrieben:Alternativ kannst du die Eingabe auch nur auf beliebige Anzahl Zahlen einschränken (setInputMask("....")); oder bei der jetzigen bleiben, per QRegExp den Inhalt überprüfen und dort bei Eingabe von etwas anderem als Zahlen die Eingabe mit lineEdit.undo() rückgängig machen (und hoff das keiner 3.14e14 eingeben will - oder deine Regexp das frisst ;) )
Okay, das wäre aber angesichts der Existenz einer QValidator Klasse in Qt kein guter Stil, da kann ich ja gleich bei meiner jetzigen Lösung bleiben ;)

Danke für deine Anregungen!
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag von padreigh »

Dein QIntValidator ist aber auch nichts anderes als ein range-begrenzter (was du nicht nutzt) setInputMask(nimmhiernurzahlen und ein vorzeichen an). Wenn du 12e-2 zulassen willst, brauchst du den QRegExpValidator.
Spinoza hat geschrieben:Was mir noch eingefallen ist, ist eine neue QValidator-Klasse von QIntValidator abzuleiten, welche immer die letzte Prüfung in einem Klassenfeld nach aussen anbietet, aber das erscheint mir etwas overkill für so ein banales feature ne extra Klasse zu schreiben. Kann doch nicht sein, dass die sonst so bedachten Qt-Macher sowas vergessen haben?
Know the [s]code[/s] API, Spinoza
Das geht zB so:

Code: Alles auswählen

#include <QLineEdit>
#include <QIntValidator>

class MLE : public QLineEdit
{
    Q_OBJECT
public:
    MLE(QWidget * parent = 0) : QLineEdit(parent)
    {
        QIntValidator * val = new QIntValidator;
        setValidator(val);
        connect(this,SIGNAL(textChanged(QString)),this,SLOT(checkEntry()));
    }

signals:
    void newValidInput(const QString &);

private slots:
    void checkEntry() {
            if (hasAcceptableInput())
            {
                emit newValidInput(text());
            }
            else
            {
                undo();
            }
    }
};
Wenn du noch den QRegExpValidator auspacken willst (bei Hours eher nicht nötig?) ginge zB sowas

Code: Alles auswählen

QString intEx = "[+-]?\\\\d+"; // kann +- muss aber nicht, 1 Nummer aufwärts
QString realEx = "[+-]?(\\\\d+|\\\\d+\\\\.\\\\d*|\\\\d*\\\\.\\\\d+)"; // kann +- muss aber nicht, kann nen int sein, kann '1234.' sein, kann '.1234' sein, kann '1234.1234' sein

QString mathEx = "("+intEx+"|"+realEx+")([eE][+-]?\\d+)?"; // kann int oder real sein, kann von eE (optional+-) 1 Nummer aufwärts sein
nagel mich auf die nicht fest, sind mit der heissen Nadel gestrickt ;) es gibt bei den Examples einen RegExpChecker - der hilft wenn du sowas testen willst.
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
Antworten