Перехват всех событий

В предыдущих разделах мы рассмотрели обработку сигналов, которые позволяют обмениваться сообщениями между компонентами. Обработка внешних событий, например, нажатий клавиш, осуществляется несколько иначе. Чтобы обработать событие необходимо наследовать класс и переопределить в нем метод со специальным названием, например, чтобы обработать нажатие клавиши следует переопределить метод keyPressEvent(). Специальные методы принимают объект, содержащий детальную информацию о событии, например, код нажатой клавиши. Все эти объекты являются наследниками класса QEvent и наследуют следующие методы:

  • accept() — устанавливает флаг, который является признаком согласия с дальнейшей обработкой события, например, если в методе closeEvent() вызывать метод accept() через объект события, то окно будет закрыто. Флаг обычно устанавливается по умолчанию. Прототип метода:
void accept()
  • ignore() — сбрасывает флаг, например, если в методе closeEvent() вызывать метод ignore() через объект события, то окно закрыто не будет. Прототип метода:
void ignore()
  • setAccepted() — если в качестве параметра указано значение true, то флаг будет установлен (аналогично вызову метода accept()), а если false — то сброшен (аналогично вызову метода ignore()). Прототип метода:
virtual void setAccepted(bool accepted)
  • isAccepted() — возвращает текущее состояние флага. Прототип метода:
bool isAccepted() const
  • registerEventType() — позволяет зарегистрировать пользовательский тип события. Метод возвращает идентификатор зарегистрированного события. В качестве параметра можно указать значение в пределах от QEvent::User (1000) до QEvent::MaxUser (65535). Метод является статическим. Прототип метода:
static int registerEventType(int hint = -1)
  • spontaneous() — возвращает true, если событие сгенерировано системой, и false, если событие сгенерировано внутри программы искусственно. Прототип метода:
bool spontaneous() const
  • type() — возвращает тип события. Прототип метода:
QEvent::Type type() const

Перечислим основные типы событий (полный список смотрите в документации по классу QEvent):

  • 0None — нет события;
  • 1Timer — событие таймера;
  • 2MouseButtonPress — нажата кнопка мыши;
  • 3MouseButtonRelease — отпущена кнопка мыши;
  • 4MouseButtonDblClick — двойной щелчок мышью;
  • 5MouseMove — перемещение мыши;
  • 6KeyPress — клавиша на клавиатуре нажата;
  • 7KeyRelease — клавиша на клавиатуре отпущена;
  • 8FocusIn — получен фокус ввода с клавиатуры;
  • 9FocusOut — потерян фокус ввода с клавиатуры;
  • 10Enter — указатель мыши входит в область компонента;
  • 11Leave — указатель мыши покидает область компонента;
  • 12Paint — перерисовка компонента;
  • 13Move — позиция компонента изменилась;
  • 14Resize — изменился размер компонента;
  • 17Show — компонент отображен;
  • 18Hide — компонент скрыт;
  • 19Close — окно закрыто;
  • 24WindowActivate — окно стало активным;
  • 25WindowDeactivate — окно стало неактивным;
  • 26ShowToParent — дочерний компонент отображен;
  • 27HideToParent — дочерний компонент скрыт;
  • 31Wheel — прокручено колесико мыши;
  • 40Clipboard — содержимое буфера обмена изменено;
  • 60DragEnter — указатель мыши входит в область компонента при операции перетаскивания;
  • 61DragMove — производится операция перетаскивания;
  • 62DragLeave — указатель мыши покидает область компонента при операции перетаскивания;
  • 63Drop — операция перетаскивания завершена;
  • 68ChildAdded — добавлен дочерний компонент;
  • 69ChildPolished — производится настройка дочернего компонента;
  • 71ChildRemoved — удален дочерний компонент;
  • 74PolishRequest — компонент настроен;
  • 82ContextMenu — событие контекстного меню;
  • 99ActivationChange — изменился статус активности окна верхнего уровня;
  • 103WindowBlocked — окно блокировано модальным окном;
  • 104WindowUnblocked — текущее окно разблокировано после закрытия модального окна;
  • 105WindowStateChange — статус окна изменился;
  • 1000User — пользовательское событие;
  • 65535MaxUser — максимальный идентификатор пользовательского события.

Перехват всех событий осуществляется с помощью метода с предопределенным названием event(). Прототип метода:

virtual bool event(QEvent *e)

Через параметр доступен объект с дополнительной информацией о событии. Этот объект отличается для разных типов событий, например, для события MouseButtonPress объект будет экземпляром класса QMouseEvent, а для события KeyPress — экземпляром класса QKeyEvent. Какие методы содержат эти классы, мы рассмотрим в следующих разделах.

Внутри метода event() следует вернуть значение true, если событие принято, и false — в противном случае. Если возвращается значение true, то родительский компонент не получит событие. Чтобы продолжить распространение события необходимо вызвать метод event() базового класса и передать ему текущий объект события. Обычно это делается так:

return QWidget::event(e);

В этом случае пользовательский класс является наследником класса QWidget и переопределяет метод event(). Если вы наследуете другой класс, то следует вызывать метод именно этого класса. Например, при наследовании класса QLabel инструкция будет выглядеть так:

return QLabel::event(e);

Рассмотрим пример перехвата нажатия клавиши, щелчка мышью и закрытия окна. Содержимое файла widget.h приведено в листинге 4.18, файла widget.cpp — в листинге 4.19, а файла main.cpp — в листинге 4.20.

Листинг 4.18. Содержимое файла widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QApplication>
#include <QWidget>
#include <QKeyEvent>
#include <QMouseEvent>

class Widget : public QWidget
{
   Q_OBJECT

public:
   Widget(QWidget *parent=nullptr);
   ~Widget();
   bool event(QEvent *e) override;
};
#endif // WIDGET_H

Листинг 4.19. Содержимое файла widget.cpp

#include "widget.h"

Widget::Widget(QWidget *parent)
   : QWidget(parent)
{}

bool Widget::event(QEvent *e)
{
   if (e->type() == QEvent::KeyPress) {
      qDebug() << "Нажата клавиша на клавиатуре";
      QKeyEvent *k = static_cast<QKeyEvent*>(e);
      qDebug() << "Код:" << k->key() << "текст:" << k->text();
   }
   else if (e->type() == QEvent::Close) {
      qDebug() << "Окно закрыто";
   }
   else if (e->type() == QEvent::MouseButtonPress) {
      qDebug() << "Щелчок мышью";
      QMouseEvent *m = static_cast<QMouseEvent*>(e);
      qDebug() << "Координаты:" << m->position();
   }
   return QWidget::event(e); // Отправляем дальше
}

Widget::~Widget() {}

Листинг 4.20. Содержимое файла main.cpp

#include "widget.h"

int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
   Widget window;
   window.setWindowTitle("Обработка событий");
   window.resize(350, 100);
   window.show();
   return app.exec();
}

Учебник C++ (Qt Creator и MinGW)
Учебник C++ (Qt Creator и MinGW) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов