My fix for the strange behaviour of QValidator.
-
I was going to ask a question about QIntValidator strange behaviour of allowing you to enter a number larger than the max value when I knew I had to search for an answer on this forum first. No solution could be found. Anyway, with the help of chatgpt I have come up with a solution. people here have helped me so I think it may help beginners like me to post the solution here:
P.S. If this is not appropriate, please delete this post. Thank you very much.#include "MainWindow.h" #include "ui_MainWindow.h" #include <QIntValidator> #include <QDoubleValidator> #include <QLineEdit> #include <QGridLayout> #include <QLabel> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); this->setGeometry(50, 50, 120, 50); QGridLayout* layout = new QGridLayout(); QLineEdit* intEdit = new QLineEdit("0"); QLineEdit* doubleEdit = new QLineEdit("0.0"); layout->addWidget(new QLabel("Enter an integer: "), 0, 0); // second pair: 1, 2 means row occupies 1 row, 2 means col occupies 2 cols. layout->addWidget(intEdit, 0, 1, 1, 2); layout->addWidget(new QLabel("Enter a double: "), 1, 0); layout->addWidget(doubleEdit, 1, 1, 1, 2); QIntValidator* intValidator = new QIntValidator(-50, 100); // intValidator->setRange(0, 100); // we can use this. intEdit->setValidator(intValidator); QString* previousValidValue = new QString(intEdit->text()); // NOTE that we use the textChanged SIGNAL so that we can check each single input character in real time. connect(intEdit, &QLineEdit::textChanged, [intEdit, intValidator, previousValidValue] { QString valueStr = intEdit->text(); int pos = 0; // Dummy variable needed by validate, but unused. // Note that only this IF CONDITION works. Nothing else will not work as expected. // A. if valueStr is not within bounds ( -50 =< valueStr <= 100), if returns true. So we call setText(previous_value) on intEdit. // To make this clear, suppose we enter 9, which is valid so the else clause runs and previousValidValue == 9. // We enter 9 again and intEdit now has 99 and valueStr = 99, valid and previousValidValue == 99. When we enter a third digit, // now intEdit contains 990 and if returns true and intEdit->setText(*previousValidValue); runs, which displays 99. // That's why we can never exceed 100. // B. if valueStr is within bounds, if returns false. So we update previousValidValue with the current valid input. // C. If we comment out the else clause, and enter a two-digit number more than once, we'll get 0 + the two-digit number. // 0 is our initial number given to the constructor of intEdit. // D. We cannot enter 1-0, i.e the minus sign after a digit. Great! if (intValidator->validate(valueStr, pos) != QValidator::Acceptable && !valueStr.isEmpty() && valueStr != "-") { intEdit->setText(*previousValidValue); } else { // Update previous valid value if current input is valid *previousValidValue = valueStr; } }); // add layout to the central widget to be displayed. this->centralWidget()->setLayout(layout); } MainWindow::~MainWindow() { delete ui; } -
N ntos has marked this topic as solved on