Qt 4.3.1 - QIntValidator
-
Hallo zusammen,
ich lerne zur Zeit Qt mit Hilfe dieses Buches: http://www.amazon.de/Qt-4-Einf%C3%BChrung-die-Applikationsentwicklung/dp/3937514120/ref=pd_bowtega_1/303-5591657-2958615?ie=UTF8&s=books&qid=1187663870&sr=1-1
In einem der ersten Beispielprogramme wird ein Zahlen-Konverter erstellt, der zwischen dem Dezimal-, Hexadezimal- und Binärsystem umwandeln kann. Als Eingabe sollen nur Werte, die sich mit einem Byte darstellen lassen, akzeptiert werden. Daher wird mit QIntValidator für das Dezimalfeld und mit QRegExpValidator für die beiden Anderen geprüft.
Der Validator für das Dezimalsystem funktioniert leider nicht: Die Eingabe wird auf 0-255 beschränkt, aber es werden auch andere beliebig hohe dreistellige Werte zugelassen.Wäre nett, wenn jemand einem Einsteiger weiterhelfen könnte.
PS.: Ich hoffe, es ist nicht zu viel Code...
ByteConverterDialog.h:
// byteConverter/ByteConverterDialog.h #ifndef BYTECONVERTERDIALOG_H #define BYTECONVERTERDIALOG_H #include <QDialog> class QLineEdit; class ByteConverterDialog : public QDialog { Q_OBJECT public: ByteConverterDialog(); private: QLineEdit* decEdit; QLineEdit* hexEdit; QLineEdit* binEdit; }; #endif // BYTECONVERTERDIALOG_H
ByteConverterDialog.cpp (gekürzt):
//byteConverter/ByteConverterDialog.cpp #include "ByteConverterDialog.h" #include <QLabel> #include <QLineEdit> #include <QPushButton> #include <QVBoxLayout> #include <QHBoxLayout> #include <QGridLayout> #include <QIntValidator> #include <QRegExpValidator> ByteConverterDialog::ByteConverterDialog() { // Erzeuge die Labels und Line-Edits und füge sie // zum editLayout hinzu QLabel* decLabel = new QLabel(tr("Dezimal")); QLabel* hexLabel = new QLabel(tr("Hexadezimal")); QLabel* binLabel = new QLabel(tr("Binär")); decEdit = new QLineEdit; hexEdit = new QLineEdit; binEdit = new QLineEdit; // Beschränke die Eingabe auf gültige Werte QIntValidator* decValidator = new QIntValidator(0, 255, decEdit); // decEdit = Elternobjekt des Validators -> automat. Löschung decEdit->setValidator(decValidator); QRegExpValidator* hexValidator = new QRegExpValidator(QRegExp("[0-9A-Fa-f]{1,2}"), hexEdit); hexEdit->setValidator(hexValidator); QRegExpValidator* binValidator = new QRegExpValidator(QRegExp("[01]{1,8}"), binEdit); binEdit->setValidator(binValidator); }
main.cpp:
// byteConverter/main.cpp #include <QApplication> #include "ByteConverterDialog.h" int main(int argc, char* argv[]) { QApplication a(argc, argv); ByteConverterDialog bc; bc.setAttribute(Qt::WA_QuitOnClose); bc.show(); return a.exec(); }
-
Hi,
Der Validator für das Dezimalsystem funktioniert leider nicht
Doch, er funktioniert wohl nur nicht so wie Du Dir das vorstellst. Wenn Du den auf 0...255 stellst lässt er beliebige bis zu 3-stellige Zahlen zu. Auch was wie 999.
Benutze zusätzlich noch das/die Signal(s) returnPressed/editingFinished oder rufe selber validate() zur Überprüfung auf.
Falls Dir das nicht gefällt - mir übrigens auch nicht - nimm auch hier einen QRegExpValidator.
QRegExp("[01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]")
cu, Bernd
-
Vorweg, ich hab mich verklickt und moagnus1 = moagnus.
Hm, das Beispiel stand so im Buch. Kann es sein, dass sich da in den letzten Qt4-Versionen was geändert hat?
Ich finde die Syntax der Funktion nur ein wenig irreführend, weil ja eigtl. ein Bereich als Argumente übergeben wird, der dann aber irgendwie doch nicht verarbeitet wird.Da führende Nullen nicht akzeptiert werden sollen, kann man die RegExp ja auch so schreiben, oder?
QRegExp("1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]")
Ich hab das Programm jetzt mal um die Signal/Slot-Verbindungen erweitert und bin dabei wieder auf etwas Seltsames gestoßen: int QString::toInt() empfängt laut Referenz zwei optionale Argumente, nämlich einen Zeiger auf bool und einen Integer, der die Basis angibt; in meinem Programm wird toInt() in den Slots verwendet, um die übermittelte Eingabe in einen Integer umzuwandeln (was fehlschlägt, wenn QString == ""). Mit der setText-Funktion wird dann in die beiden anderen QLineEdits der ins entsprechende Stellenwertsystem konvertierte Wert eingetragen.
Problem: Die Aktualisierung erfolgt nur, wenn beim Slot in das seinem Namen entsprechende System umgewandelt wird, also bei decChanged() mit toInt(&ok, [10]), bei hexChanged() mit toInt(&ok, 16) usw.
Ich verstehe hier wieder nicht, warum nicht einfach ins Dezimalsystem gecastet werden kann, da doch bei setText wieder mit number ins dem Feld zugehörige Wertesystem gewandelt wird.Hier die vollständige und erweiterte ByteConverterDialog.cpp:
// byteConverter/ByteConverterDialog.cpp #include "ByteConverterDialog.h" #include <QLabel> #include <QLineEdit> #include <QPushButton> #include <QVBoxLayout> #include <QHBoxLayout> #include <QGridLayout> // #include <QIntValidator> #include <QRegExpValidator> ByteConverterDialog::ByteConverterDialog() { // Erzeuge die notwendigen Layouts QVBoxLayout* mainLayout = new QVBoxLayout(this); QGridLayout* editLayout = new QGridLayout; QHBoxLayout* buttonLayout = new QHBoxLayout; mainLayout->addLayout(editLayout); mainLayout->addStretch(); mainLayout->addLayout(buttonLayout); // Erzeuge die Labels und Line-Edits und füge sie // zum editLayout hinzu QLabel* decLabel = new QLabel(tr("Dezimal")); QLabel* hexLabel = new QLabel(tr("Hexadezimal")); QLabel* binLabel = new QLabel(tr("Binär")); decEdit = new QLineEdit; hexEdit = new QLineEdit; binEdit = new QLineEdit; editLayout->addWidget(decLabel, 0, 0); editLayout->addWidget(decEdit, 0, 1); editLayout->addWidget(hexLabel, 1, 0); editLayout->addWidget(hexEdit, 1, 1); editLayout->addWidget(binLabel, 2, 0); editLayout->addWidget(binEdit, 2, 1); // Erzeuge den "Beenden"-Knopf und füge ihn zum // buttonLayout hinzu QPushButton* exitButton = new QPushButton(tr("Beenden")); buttonLayout->addStretch(); buttonLayout->addWidget(exitButton); exitButton->setDefault(true); setWindowTitle(tr("Zahlen-Konverter")); // Beschränke die Eingabe auf gültige Werte QRegExpValidator* decValidator = new QRegExpValidator(QRegExp("1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]"), decEdit); // decEdit = Elternobjekt des Validators -> automat. Löschung decEdit->setValidator(decValidator); QRegExpValidator* hexValidator = new QRegExpValidator(QRegExp("[0-9A-Fa-f]{1,2}"), hexEdit); hexEdit->setValidator(hexValidator); QRegExpValidator* binValidator = new QRegExpValidator(QRegExp("[01]{1,8}"), binEdit); binEdit->setValidator(binValidator); connect(exitButton, SIGNAL(clicked()), this, SLOT(accept())); connect(decEdit, SIGNAL(textChanged(const QString&)), this, SLOT(decChanged(const QString&))); connect(hexEdit, SIGNAL(textChanged(const QString&)), this, SLOT(hexChanged(const QString&))); connect(binEdit, SIGNAL(textChanged(const QString&)), this, SLOT(binChanged(const QString&))); } void ByteConverterDialog::decChanged(const QString& newValue) { bool ok; int num = newValue.toInt(&ok); // optionales Argument -> erfolgreiche Konvertierung: true; ansonsten false if (ok) { hexEdit->setText(QString::number(num, 16)); binEdit->setText(QString::number(num, 2)); } else { hexEdit->setText(""); // wenn Eingabe leer ist, ansonsten: Validator verhindert Fehlschlagen binEdit->setText(""); } } void ByteConverterDialog::hexChanged(const QString& newValue) { bool ok; int num = newValue.toInt(&ok, 16); if (ok) { decEdit->setText(QString::number(num)); binEdit->setText(QString::number(num, 2)); } else { decEdit->setText(""); binEdit->setText(""); } } void ByteConverterDialog::binChanged(const QString& newValue) { bool ok; int num = newValue.toInt(&ok, 2); if (ok) { decEdit->setText(QString::number(num)); hexEdit->setText(QString::number(num, 16)); } else { decEdit->setText(""); hexEdit->setText(""); } }
Ich hoffe, ihr versteht mein Problem und danke im Voraus für alle Antworten.
PS.: RegExp funktioniert prächtig.
-
Morgen,
Hm, das Beispiel stand so im Buch. Kann es sein, dass sich da in den letzten Qt4-Versionen was geändert hat?
Weis ich nicht, kenne Qt auch erst seit Version 4. Frage das vielleicht mal hier:
http://qtforum.de/forum/
http://www.qtforum.org/index.html
http://www.qtcentre.org/forum/Ich finde die Syntax der Funktion nur ein wenig irreführend, weil ja eigtl. ein Bereich als Argumente übergeben wird, der dann aber irgendwie doch nicht verarbeitet wird.
Der Bereich wird schon verarbeitet, der Validator überprüft aber nur die Gültigkeit und setzt nicht auch zusätzlich die Eingabemaske so dass nur Eingaben im erlaubten Bereich zulässig sind.
Was M.E. zumindest Schade ist.Da führende Nullen nicht akzeptiert werden sollen, kann man die RegExp ja auch so schreiben, oder?
QRegExp("1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]")
Eigentlich nicht. 1?[0-9]?[0-9] erlaubt schon eine 0 am Anfang da die führende 1 ja optional ist. Diese löscht wohl dann bei der Eingabe der nächsten Ziffer das LineEdit selber??
Nimm vielleicht sowas: [1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-5]
Dein weiteres Problem verstehe ich nicht.
cu, Bernd
-
Wenn ich dich richtig verstehe, meinst du, dass das Eingabefeld nicht "überwacht" wird, sondern nur der Wert der am Ende drin steht überprüft wird und nur weiterverarbeitet wird, wenn er im Gültigkeitsbereich liegt. Ja?
Zur RegExp (letzter Versuch ;)):
0|[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-5]
Hm, das Problem ist eigtl. ganz einfach, ich habs wohl zu kompliziert gemacht.
Folgender Codeausschnitt:
void ByteConverterDialog::hexChanged(const QString& newValue) { bool ok; int num = newValue.toInt(&ok, 16); if (ok) { binEdit->setText(QString::number(num, 2));
Wenn ich bei toInt() die 16 weglasse, wird ins Dezimalsystem gewandelt. Ich dachte mir, dass es ja eigtl. egal ist, in welches System gewandelt wird, da ja dann number() aufgerufen wird, was nochmals umwandelt. Wenn ich allerdings bei der Funktion hexChanged die 16 bei toInt() weglasse oder bei der Fkt. binChanged die 2, werden die LineEdits nicht mehr richtig synchronisiert (nur noch bei ner 0 glaub ich).
Danke für deine schnellen Antworten
-
Morgen,
Wenn ich dich richtig verstehe, meinst du, dass das Eingabefeld nicht "überwacht" wird, sondern nur der Wert der am Ende drin steht überprüft wird und nur weiterverarbeitet wird, wenn er im Gültigkeitsbereich liegt. Ja?
Beinahe. Nur wenn der Wert im Gültigkeitsbereich liegt werden die Signale returnPressed und editingFinished gesendet. Aus der Qt-Hilfe:
Note that if there is a validator set on the line edit, the returnPressed()/editingFinished() signals will only be emitted if the validator returns QValidator::Acceptable.
Zur RegExp (letzter Versuch ;)):
0|[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-5]Ja, sollte eigentlich passen.
Ich dachte mir, dass es ja eigtl. egal ist, in welches System gewandelt wird,
Es wird da nicht in ein 16-er oder in ein 2-er System sondern aus dem 16-er bzw. aus dem 2-er System in eine Dezimalzahl gewandelt. Da brauchst Du die 16 bzw. 2 schon. Ansonsten funktionieren hex nur die 'Zahlen' 0-9 und bin nur die 0.
cu, Bernd
-
Vielen Dank für die geduldigen Erklärungen. Ich hab jetzt alles verstanden