БлогNot. QT: простой виджет "суммирование стека чисел"

QT: простой виджет "суммирование стека чисел"

Сделаем виджет как в этой заметке, если в Вашем QT появились какие-то дополнительные шаги при создании проекта - оставляем выбор по умолчанию, нажимая кнопку "Далее".

Здесь сознательно не использовано назначение одного обработчика нескольким кнопкам, программное создание массива кнопок и т.п. приёмы из этой статьи, код максимально облегчен.

По нажатию кнопки "+" добавляем в стек то, что определяется как число в поле ввода, по "-" удаляем, по "=" суммируем числа из стека, по "C" очищаем стек.

Также код показывает следующие типовые моменты:

  • логическое создание несложного интерфейса "по строкам" сетки QGridLayout;
  • типовые настройки окна виджета, включая позиционирование по центру основного экрана. Для этого виджету по-прежнему нужно передавать ссылку на экземпляр родительского приложения QApplication (у нас parent), но часто применяемый способ центрирования
    parent->desktop()->availableGeometry()

    согласно документации по новым версиям, устарел, и теперь нужно

    parent->screens().first()->geometry()
  • базовое преобразование строки QString в вещественное число и вещественного числа в строку QString;
  • программное добавление сигналов и слотов, в том числе, обработка двух разных сигналов одним слотом (элемент в стек можно добавлять как кнопкой "+", так и нажатием Enter в поле ввода);
  • поддержка списка строк в QTextEdit без лёгких в написании, но трудоёмких при расчётах операций по преобразованию QTextEdit в QStringList и обратно, как здесь;
  • хотя мы поддерживаем "стекоподобную" функциональность, использовать именно QStack с его методами, автоматически удаляющими элементы при извлечении, незачем, обычный QVector гораздо удобнее;
  • с другой стороны, платой за отсутствие списка служит необходимость удалять "вручную" последнюю строку из QTextEdit, это делает метод removeLastLineFromQTextEdit, которому передаётся указатель на QTextEdit, чтобы метод можно было применять отдельно от класса. В реальности наши данные всё равно хранятся в векторе и текстовое поле служит лишь для иллюстрации. "Вытащить" из QVector stack все строки мы могли и простым
    QList <QString> ql = stack.toList();

    а объединить потом обратно и заменить содержимое QTextEdit stackList столь же лёгким

    QString qs = ql.join('\n');
    stackList->clear();
    stackList->append(qs);

Ниже прикреплены скриншот приложения и архив с проектом.

скриншот приложения в работе
скриншот приложения в работе

 Скачать этот проект QT 5.10+ в архиве .zip, папка уже создана внутри архива (3 Кб)

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

protected:
 virtual void keyReleaseEvent(QKeyEvent *event);
 virtual void mousePressEvent (QMouseEvent *);
 virtual void mouseMoveEvent (QMouseEvent *);

В конструкторе виджета предусмотрим слежение за перемещением мыши (по умолчанию отслеживаются только нажатия кнопок):

setMouseTracking (true);

Обработчик нажатия клавиш будет получать их коды, обрабатывая только те, что дублируют действие кнопок виджета.

void Widget::keyReleaseEvent(QKeyEvent *event) {
 int key=event->key(); //целочисленный код клавиши
 switch (key) {
  case Qt::Key_Plus:
   event->ignore(); //Отменить дальнейшую обработку события
   this->deleteLastChar(displaystring); //Удалить завешающий символ из QLineEdit
   this->b1Clicked(); //Вызвать слот-обработчик соответствующнй кнопки
  break;
  case Qt::Key_Minus:
   event->ignore();
   this->deleteLastChar(displaystring);
   this->b2Clicked();
  break;
  case Qt::Key_Escape:
   event->ignore();
   this->deleteLastChar(displaystring);
   this->b3Clicked();
  break;
  case Qt::Key_Equal:
   event->ignore();
   this->deleteLastChar(displaystring);
   this->b4Clicked();
  break;
  default: //Здесь можно обрабатывать другие коды клавиш
  break;
 }
}

Метод для удаления последнего символа из QLineEdit пришлось написать отдельно, по умолчанию стандартный виджет просто так не "отдаст" своего символа.

void Widget::deleteLastChar (QLineEdit *q) {
 int len = q->text().length();
 q->setCursorPosition(len -1);
 q->setText(q->text().remove(len - 1,1));
}

Обработчик событий от мыши будет просто выводить текущие координаты курсора в строке заголовка окна виджета.

void Widget::mousePressEvent(QMouseEvent *event) { //клик мышью
 //if (event->button()==Qt::LeftButton) { //Какая кнопка мыши нажата
  QPoint position = event->pos(); //Позиция нажатия
  int pos = this->windowTitle().indexOf(':');
  QString title = pos > -1 ? this->windowTitle().remove(pos,this->windowTitle().size() - pos) : this->windowTitle();
  this->setWindowTitle (title + ": " +
   QString::number(position.x())+","+QString::number(position.y()));
 //}
}
void Widget::mouseMoveEvent(QMouseEvent *event) { //перемещение курсора 
 this->mousePressEvent(event);
}

Мы получили небольшое приложение, иллюстрирующее основные возможности по разработке несложных виджетов.

 Скачать этот проект QT 5.10+ в архиве .zip, папка уже создана внутри архива (4 Кб)


теги: программирование c++ qt список

13.02.2021, 14:11; рейтинг: 45