QT message mechanism and events - mouse events, keyboard press events, drawing events, timer event processing

event

  • Events are emitted at different times by the system or Qt itself. When the user presses the mouse, types on the keyboard, or when the window needs to be redrawn, a corresponding event will be emitted. Some events are emitted in response to user operations, such as keyboard events. Other events are automatically issued by the system, such as timer events.

Qt message loop mechanism

  • The Qt program needs to create aQApplicationobject and then call itsexecFunction, this function is to start Qt's event loop. in executionexecAfter the function, the program will enter the event loop to listen for the application's events.

  • When the application listensevent triggerFinally, first hand the request toevent filter, filtered and then handed over toevent dispatcher, handed over by the event dispatcher to the specificevent handlerfor processing.
    Insert image description here

  • Event filters, event dispatchers and event handlers all handle events by default. If we want to handle events ourselves, we can rewrite the corresponding event functions. Then perform corresponding processing in the corresponding event function.

  • Generally speaking, there are many scenarios for rewriting event processing functions. Event filtering and event distribution can basically be left to the system for processing, and we don't have to handle it ourselves. In order to illustrate the role of event filters and event dispatchers, the event filtering function and event dispatching function are also rewritten below.

  • Since it is common to override event handler functions, you can first view event processing when reading, and then view event filtering and event distribution.

event filtering

event filter function

  • bool eventFilter(QObject *watched, QEvent *event);
  • The return value is of bool type. If it returns true, it means that the user wants to handle this event and not distribute the event downward.

Example

  • head File
  •   #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      #include <QEvent>
      
      namespace Ui {
          
          
      class Widget;
      }
      
      class Widget : public QWidget
      {
          
          
          Q_OBJECT
      
      public:
          explicit Widget(QWidget *parent = 0);
          ~Widget();
      protected:
      
          // 键盘按下事件
          void keyPressEvent(QKeyEvent *event);
      
          // 事件分发
          bool event(QEvent* ev);
      
          // 重写事件过滤器函数
          bool eventFilter(QObject *watched, QEvent *event);
      private:
          Ui::Widget *ui;
      };
      
      #endif // WIDGET_H
    
  • Source File
  •   #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QDebug>
      #include <QMouseEvent>
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          
          
          ui->setupUi(this);
      
          // 安装事件过滤器
          installEventFilter(this);
      }
      
      Widget::~Widget()
      {
          
          
          delete ui;
      }
      
      void Widget::keyPressEvent(QKeyEvent *event)
      {
          
          
          // 判断键盘按下事件
          if(event->type() == QEvent::KeyPress){
          
          
              QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
              // 判断按下的是否为tab键
              if(keyEvent->key() == Qt::Key_Tab){
          
          
                  QMessageBox::question(this, "提示", "事件处理函数中Tab键按下", QMessageBox::Yes);
              }
          }
      }
      
      bool Widget::event(QEvent *ev)
      {
          
          
          // 判断键盘按下事件
          if(ev->type() == QEvent::KeyPress){
          
          
              QKeyEvent* keyEvent = static_cast<QKeyEvent*>(ev);
              // 判断按下的是否为tab键
              if(keyEvent->key() == Qt::Key_Tab){
          
          
                  QMessageBox::question(this, "提示", "事件分发函数中Tab键按下", QMessageBox::Yes);
      
                  // 返回true, 表示自己处理这个事件,不向下分发了,这样对应的事件处理函数就接收不到该事件了
                  return true;
              }
          }
      
          // 其他事件交给父类,默认处理
          return QWidget::event(ev);
      }
      
      bool Widget::eventFilter(QObject *watched, QEvent *event)
      {
          
          
          // 判断是哪个窗口,这里是当前窗口
          if(watched == this){
          
          
      
              if(event->type() == QEvent::KeyPress){
          
          
                  QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
                  // 判断按下的是否为tab键
                  if(keyEvent->key() == Qt::Key_Tab){
          
          
                      QMessageBox::question(this, "提示", "Tab键按下", QMessageBox::Yes);
      
                      // 返回true, 表示自己处理这个事件,不向下分发了
                      // 这样不仅事件处理函数接收不到该事件,事件分发函数也接受不到该事件
                      return true;
                  }
              }
          }
      
      	// 其他事件交给系统处理
          return QWidget::eventFilter(watched, event);
      }
    
    
  • If an event is processed in the event filter and is not passed down, the corresponding event will not be received by the event dispatcher or event handler.

event distribution

event dispatch function

  • bool event(QEvent* ev);
  • The return value is of bool type. If it returns true, it means that the user wants to handle this event and not distribute the event downward.

Example

  • Let's demonstrate through an example. In the event distribution function, the keyboard's tab key press event is processed, and the event is not passed down after processing, so that the corresponding event processing function cannot receive the event.
  • head File
  •   #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      #include <QEvent>
      
      namespace Ui {
          
          
      class Widget;
      }
      
      class Widget : public QWidget
      {
          
          
          Q_OBJECT
      
      public:
          explicit Widget(QWidget *parent = 0);
          ~Widget();
      protected:
      
          // 键盘按下事件
          void keyPressEvent(QKeyEvent *event);
      
          // 事件分发
          bool event(QEvent* ev);
      private:
          Ui::Widget *ui;
      };
      
      #endif // WIDGET_H
    
  • Source File
  •   #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QDebug>
      #include <QMouseEvent>
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          
          
          ui->setupUi(this);
      }
      
      Widget::~Widget()
      {
          
          
          delete ui;
      }
      
      void Widget::keyPressEvent(QKeyEvent *event)
      {
          
          
          // 判断键盘按下事件
          if(event->type() == QEvent::KeyPress){
          
          
              QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
              // 判断按下的是否为tab键
              if(keyEvent->key() == Qt::Key_Tab){
          
          
                  QMessageBox::question(this, "提示", "事件处理函数中Tab键按下", QMessageBox::Yes);
              }
          }
      }
      
      bool Widget::event(QEvent *ev)
      {
          
          
          // 判断键盘按下事件
          if(ev->type() == QEvent::KeyPress){
          
          
              QKeyEvent* keyEvent = static_cast<QKeyEvent*>(ev);
              // 判断按下的是否为tab键
              if(keyEvent->key() == Qt::Key_Tab){
          
          
                  QMessageBox::question(this, "提示", "Tab键按下", QMessageBox::Yes);
      
                  // 返回true, 表示自己处理这个事件,不向下分发了,这样对应的事件处理函数就接收不到该事件了
                  return true;
              }
          }
      
      
          // 其他事件交给父类,默认处理
          return QWidget::event(ev);
      }
    
  • Demo
    Insert image description here
  • As you can see from the example, although the tab key press is processed in the event processing function, the event processing function is not triggered because the tab key press event is not passed down in the event distribution function.

event handling

  • After the event is triggered, it is first filtered through the event filter, and then passed through the event dispatcher, and is sent to a specific event processor. The default event processor will also automatically process the event. If you want to handle it yourself, you can rewrite the event processing. function.
  • QObject class is the parent class of all Qt classes, so all Qt classes can inherit the event processing functions of the QObject class. The event functions of the QObject class are mainly timer event functions. Automatically triggered bysystem.
  • QWidget class is the event function of all Qt window classes, so all Qt window classes can inherit the event processing functions of the QWidget class. The QWidget class has many event functions, such as keyboard Press events, mouse movement events, etc., the event functions of the QWidget class are mainly triggered byusers.

Event handling function of QObject class

  • timer event function
  • virtual void timerEvent(QTimerEvent *event)

Event handler function of QWidget class

  • window close event function
  • virtual void closeEvent(QCloseEvent *event)
  • Window hide event function
  • virtual void hideEvent(QHideEvent *event)
  • Window display event function
  • virtual void showEvent(QShowEvent *event)
  • Window resize event function
  • virtual void resizeEvent(QResizeEvent *event)
  • Keyboard press event function
  • virtual void keyPressEvent(QKeyEvent *event)
  • Keyboard release event function
  • virtual void keyReleaseEvent(QKeyEvent *event)
  • Mouse double click event function
  • virtual void mouseDoubleClickEvent(QMouseEvent *event)
  • Mouse move event function
  • virtual void mouseMoveEvent(QMouseEvent *event)
  • Mouse press event function
  • virtual void mousePressEvent(QMouseEvent *event)
  • Mouse release event function
  • virtual void mouseReleaseEvent(QMouseEvent *event)
  • Drawing event function
  • virtual void paintEvent(QPaintEvent *event)

Example 1: Window event handling

  • Next we use an example to demonstrate the closing of window and window resizing< /span>How to handle the event of
  • Create a class that inherits from the QWidget class
  • head File
  •   #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      
      namespace Ui {
          
          
      class Widget;
      }
      
      class Widget : public QWidget
      {
          
          
          Q_OBJECT
      
      public:
          explicit Widget(QWidget *parent = 0);
          ~Widget();
      protected:
          // 重写窗口关闭事件函数
          void closeEvent(QCloseEvent *event);
          // 重写重绘窗口大小事件函数
          void resizeEvent(QResizeEvent *event);
      private:
          Ui::Widget *ui;
      };
      
      #endif // WIDGET_H
    
  • Source File
  •   #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QCloseEvent>
      #include <QResizeEvent>
      #include <QDebug>
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          
          
          ui->setupUi(this);
      }
      
      Widget::~Widget()
      {
          
          
          delete ui;
      }
      
      void Widget::closeEvent(QCloseEvent *event)
      {
          
          
          int retStatus = QMessageBox::question(this, "提示", "确定关闭窗口吗?", QMessageBox::Yes | QMessageBox::No);
          if(retStatus == QMessageBox::Yes){
          
          
              // 处理该事件,也就是关闭窗口
              event->accept();
          }else{
          
          
              // 忽略该事件,也就是不关闭窗口
              event->ignore();
          }
      }
      
      void Widget::resizeEvent(QResizeEvent *event)
      {
          
          
          qDebug()<<"old size : "<<event->oldSize();
          qDebug()<<"new size : "<<event->size();
      }
    
  • Show results
    Please add image description
    Please add image description

Example 2: Mouse event handling

  • Realize another pairmouse pressed,mouse released and mouse movement event processing flow.
  • head File
  •   #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      
      namespace Ui {
          
          
      class Widget;
      }
      
      class Widget : public QWidget
      {
          
          
          Q_OBJECT
      
      public:
          explicit Widget(QWidget *parent = 0);
          ~Widget();
      protected:
          // 重写鼠标按下事件
          void mousePressEvent(QMouseEvent* event);
          // 重写鼠标松开事件
          void mouseReleaseEvent(QMouseEvent* event);
          // 重写鼠标移动事件
          void mouseMoveEvent(QMouseEvent* event);
      
      private:
          Ui::Widget *ui;
      };
      
      #endif // WIDGET_H
    
  • Source File
  •   #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QDebug>
      #include <QMouseEvent>
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          
          
          ui->setupUi(this);
      
          // 设置鼠标被追踪
          // 不设置该属性,鼠标按下移动时才能触发鼠标移动事件函数
          // 设置该属性后,不管鼠标是否按下,鼠标移动事件函数都会被触发
          // this->setMouseTracking(true);
      
          ui->label->setText("鼠标正常");
      }
      
      Widget::~Widget()
      {
          
          
          delete ui;
      }
      
      void Widget::mousePressEvent(QMouseEvent *event)
      {
          
          
          if(event->button() == Qt::LeftButton){
          
          
              ui->label->setText("鼠标左键按下");
          }else if(event->button() == Qt::RightButton){
          
          
              ui->label->setText("鼠标右键按下");
          }else{
          
          
              ui->label->setText("鼠标按下");
          }
      }
      
      void Widget::mouseReleaseEvent(QMouseEvent *event)
      {
          
          
          ui->label->setText("鼠标松开");
      }
      
      void Widget::mouseMoveEvent(QMouseEvent *event)
      {
          
          
          QString msg;
          msg = "鼠标移动(" + QString::number(event->x()) + "," + QString::number(event->y()) + ")";
          ui->label->setText(msg);
      }
    
  • Show results
    Please add image description
    Please add image description

Example 3: Drawing event handling

  • Processing drawing events is a very commonly used function. Here is a simple explanation through an example.
  • head File
  •   #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      #include <QEvent>
      #include <QPainter>
      
      namespace Ui {
          
          
      class Widget;
      }
      
      class Widget : public QWidget
      {
          
          
          Q_OBJECT
      
      public:
          explicit Widget(QWidget *parent = 0);
          ~Widget();
      protected:
      
          // 绘图事件
          void paintEvent(QPaintEvent* e);
      
      private:
          Ui::Widget *ui;
      };
      
      #endif // WIDGET_H
    
  • Source File
  •   #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QDebug>
      
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          
          
          ui->setupUi(this);
      
      }
      
      Widget::~Widget()
      {
          
          
          delete ui;
      }
      
      void Widget::paintEvent(QPaintEvent *e)
      {
          
          
          // 实例化画家对象, this表示绘图设备是当前窗口
          QPainter painter(this);
      
          // 画线
          painter.drawLine(QPoint(0, 0), QPoint(100, 100));
      
          // 设置画笔(红色)
          QPen pen(QColor(255, 0, 0));
      
          // 设置画笔宽度
          pen.setWidth(3);
          // 设置画笔风格
          pen.setStyle(Qt::DotLine);
          painter.setPen(pen);
      
          // 画矩形
          painter.drawRect(QRect(0, 0, 100, 100));
      
          // 设置画刷
          QBrush brush(Qt::green);
          // 设置画刷风格
          brush.setStyle(Qt::Dense1Pattern);
          painter.setBrush(brush);
      
          // 画圆
          painter.drawEllipse(QPoint(150, 50), 50, 50);
      
          // 画文字
          painter.drawText(QRect(0, 150, 150, 150), "HELLO");
      
          // 画图片
          painter.drawPixmap(100, 100, QPixmap(":/gray.jpg"));
      }
    
  • Demo
    Insert image description here
  • The drawing event is special. It is automatically triggered by the system by default, but it can also be triggered manually. That is to call the update() function in the function. After the call, the drawing event will be automatically triggered, and the corresponding drawing event processing function will be executed. For example, the update() function can be called in the mouse click slot function, which will not be demonstrated here.

Example 4: Timer event handling

  • The timer event is triggered by the system, and the processing function can be rewritten to perform corresponding operations. This is also a very commonly used function.
  • head File
  •   #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      #include <QEvent>
      #include <QTimerEvent>
      
      namespace Ui {
          
          
      class Widget;
      }
      
      class Widget : public QWidget
      {
          
          
         Q_OBJECT
      
      public:
         explicit Widget(QWidget *parent = 0);
         ~Widget();
      protected:
      
         // 定时器事件处理函数
         void timerEvent(QTimerEvent *e);
      
      private:
         Ui::Widget *ui;
      
         // 定时器id
         int timerId;
      };
      
      #endif // WIDGET_H
    
  • Source File
  •   #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QDebug>
      
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          
          
          ui->setupUi(this);
      
          // 启动定时器,定时事件为1秒
          timerId = startTimer(1000);
      }
      
      Widget::~Widget()
      {
          
          
          // 停止定时器
          killTimer(timerId);
      
          delete ui;
      }
      
      void Widget::timerEvent(QTimerEvent *e)
      {
          
          
          qDebug()<<"定时器事件触发";
      }
    

Guess you like

Origin blog.csdn.net/new9232/article/details/134625282