QValidator примеры использования

      Комментарии к записи QValidator примеры использования отключены

В этой теме 0 ответов, 1 участник, последнее обновление  Васильев Владимир Сергеевич 2 мес. назад.

  • Автор
    Сообщения
  • #4004

    Когда пользователю предлагается ввести какие-либо данные в текстовое поле, то довольно часто можно получить что-то абсолютно неожиданное. Пользователь может ввести числа прописью, использовать неверный десятичный разделитель или забыть указать код города в телефонном номере. Таким образом, в большинстве случаев, необходимо проверять правильность(допустимость) указанной информации.

    Qt содержит класс QValidator, проверяющий корректность введенных данных. Данных класс не может быть использован напрямую. Для проверки данных придется либо воспользоваться готовыми подклассами QIntValidator, QDoubleValidator, QRegExpValidator, либо написать подкласс самим.

    В метод validate(QString & input, int & pos) передается строка для проверки и позиция курсора. Метод может возвращать следующие значения:

    1. QValidator::Invalid — строка недопустима;
    2. QValidator::Acceptable — строка допустима;
    3. QValidator::Intermediate — строка не может быть принята в текущем состоянии, но она может стать допустимой.

    Кроме того, валидатор может быть установлен методом setValidator для поля ввода, при этом Qt просто не позволит пользователю ввести некорректные данные.

    Проверка корректности ввода чисел. QDoubleValidator

    Напишем программу, вычисляющую сумму двух дробных чисел, при этом ограничим диапазон вводимых значений. Работа программы приведена на рисунке (не видно, что мы пытались вводить буквы и более длинные числа, т.к. при этом содержимое поля не изменяется):

    Для создания такого приложения я использовал QtDesigner, прочитать больше про это можно в статье «Собственные виджеты в Qt Designer«. Для этого я создал проект с типом «приложение Qt Widgets», мышкой добавил на форму элементы и установил им имена:

    После этого изменил содержимое mainwindow.h добавив в класс объект валидатора и слот, который будет вызываться при каждом изменении содержимого полей ввода:

    #include <QMainWindow>
    #include <QDoubleValidator>
    namespace Ui {
    class MainWindow;
    }
    class MainWindow : public QMainWindow {
    Q_OBJECT
    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    protected slots:
    void on_changed();
    private:
    Ui::MainWindow *ui;
    QDoubleValidator m_doubleValidator;
    };

    В конструкторе класса создаю валидатор, который будет разрешать вводить числа только в диапазоне от -100 до 1000 и с двумя разрядами дробной части, задает валидатору нотацию, устанавливает валидатор к полям ввода и соединяет сигналы изменения содержимого поля ввода со слотом:

    MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
    ui(new Ui::MainWindow), m_doubleValidator(-100, 1000, 2, this) {
    ui->setupUi(this);
    m_doubleValidator.setNotation(QDoubleValidator::StandardNotation);
    ui->a->setValidator(&m_doubleValidator);
    ui->b->setValidator(&m_doubleValidator);
    connect(ui->a, SIGNAL(textChanged(QString)), this, SLOT(on_changed()));
    connect(ui->b, SIGNAL(textChanged(QString)), this, SLOT(on_changed()));
    }

    Используя метод setNotation(Notation) класса QDoubleValidator можно установить допустимость научной нотации:

    • QDoubleValidator::StandardNotation — стандартная нотация(Например: 1,124 или -2).
    • QDoubleValidator::ScientificNotation — научная нотация, т.е. число может иметь экспоненциальную часть(Например: 2,7E-3 или 3,3E+2)

    В обработчике изменения значения в поле преобразуем введенный текст в double, вычисляем сумму и выводим ее:

    void MainWindow::on_changed() {
    double result;
    result = ui->a->text().toDouble() + ui->b->text().toDouble();
    ui->sum->setText(QString::number(result));
    }

    Обратите внимание, что при использовании научной нотации пользователь сможет ввести некорректные значение в поле, ведь не смотря на то, что 10000 является некорректным значением в нашем случае — значение 10000E-3 вполне корректно. Поэтому если вы используете ScientificNotation проверку надо выполнять методом validate перед обработкой данных. Мы же используем стандартную нотацию, поэтому Qt не позволит ввести неверные данные.

    Кроме того, если вам надо проверить, что введено дробное число (без проверки диапазона) — сделать это можно при преобразовании строки методом toDouble, т.к. ее аргумент — флаг *bool ok. В этом случае можно обойтись без валидатора и это нормальное решение если вы используете научную нотацию — ведь вызов validate(ui->a->text(), 0) выглядит не лучше. Однако, валидаторы очень полезны при проверке корректности вводимых строк.

    Проверка корректности строк. QRegExpValidator

    Регулярные выражения(regular expressions, regexp, RE, регэкспы) — система поиска текстовых фрагментов в строках, основанная на специальной системе записи шаблонов для поиска. В библиотеке Qt регулярные выражения представлены объектами класса QRegExp — ранее с помощью этого класса мы вытаскивали нужную нам информацию с веб-станицы: Парсер сайта на Qt, использование QRegExp. Для проверки строки на наличие регулярного выражения используется класс QRegExpValidator.

    В управляющих последовательностях используется обратная косая черта \. Некоторые символы, используемые при записи регулярных выражений рассматриваются не как обычные символы, а как имеющие специальное значение — метасимволы. Основные метасимволы:

    • . (точка) — любой символ, включая новую строку
    • \s — пробел(QChar::isSpace())
    • \S — не пробел
    • \w — текстовый символ (QChar::isLetterOrNumber(), QChar::isMark(), или '_')
    • \W — не текстовый символ
    • \d — цифра (QChar::isDigit())
    • \D — не цифра
    • \xhhhh — символ Unicode в шестнадцатеричном виде
    • \0ooo — символ ASCII/Latin1 в восьмеричном виде

    Необходимо помнить об управляющих последовательностях C++. Они тоже работают. Так так компилятор C++ преобразует обратные косые черты в строки, то \d в С++ необходимо будет записать как \\d, а \\\\\\.
    По умолчанию выражения имеют квантификатор (1,1), т.е. повторяются 1 раз.
    Основные кванторы:

    • Е? — одно или 0 повторений выражения
    • E+ — одно или более повторений выражения, тоже, что и E{1,}
    • E*0 или более повторений выражения, тоже, что и E{0,}
    • Е{n}n повторений, тоже, что и E{n,n}
    • E{n,}n повторений и более
    • E{,m} — до m повторений
    • E{n,m} — от n до m повторений

    Данные квантификаторы являются жадными. Квантификаторы могут быть сделаны не жадными с помощью метода void QRegExp::setMinimal(bool minimal).

    Основные утверждения:

    1. ^ — начало строки
    2. $ — конец строки

    Разработаем приложение, в котором будет проверяться корректность номера телефона и номера кредитной карты (вида ABCD-1234-1234):

    Номер телефона начинается с кода страны, который может иметь одну или 2 цифры, затем, в скобках, следует код города (от 3 до 5 цифр) и наконец сам номер(от 2 до 7 цифр). Составим регулярные выражения:
    номер карты — ^[A-Z]{4}\-[0-9]{4}\-[0-9]{4}$
    номер телефона — ^\+\d{1,2}\(\d{3,5}\)\d{2,7}$
    Строки С++ будут выглядеть ^[A-Z]{4}\\-[0-9]{4}\\-[0-9]{4}$ и ^\\+\\d{1,2}\\(\\d{3,5}\\)\\d{2,7}$ соответственно.

    Добавим в предыдущий проект класс формы QtDesigner, на форму кинем элементы интерфейса, дадим им имена:

    В функцию main() добавим код создания объекта этого окна и его отображения:

    int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    Regexpvalidator_example regexpvalidator_example;
    regexpvalidator_example.show();
    return a.exec();
    }

    В класс окна добавим два валидатора:

    namespace Ui {
    class Regexpvalidator_example;
    }
    class Regexpvalidator_example : public QWidget {
    Q_OBJECT
    public:
    explicit Regexpvalidator_example(QWidget *parent = 0);
    ~Regexpvalidator_example();
    private:
    Ui::Regexpvalidator_example *ui;
    QRegExpValidator m_card_validator, m_phone_validator;
    };

    В конструкторе инициализируем валидаторы регулярными выражениями и соединим их с полями ввода:

    Regexpvalidator_example::Regexpvalidator_example(QWidget *parent)
    : QWidget(parent),
    ui(new Ui::Regexpvalidator_example),
    m_card_validator(QRegExp("^[A-Z]{4}\\-[0-9]{4}\\-[0-9]{4}$")),
    m_phone_validator(QRegExp("^\\+\\d{1,2}\\(\\d{3,5}\\)\\d{2,7}$")) {
    ui->setupUi(this);
    ui->card->setValidator(&m_card_validator);
    ui->phone->setValidator(&m_phone_validator);
    }

    Теперь в поля не получится ввести совсем неверные значения — в начало номера карты не получится поместить цифры., Однако, мы сможем ввести, например номер карты, состоящий из единственной буквы. Проверить соответствие строки выражению можно с помощью метода validate.

    Исходный код проекта можно взять в репозитории.

Для ответа в этой теме необходимо авторизоваться.