Qt event system: event processing and delivery in Qt

1. Introduction

In Qt, an event is an object that inherits from the QEvent class. Common ones include keyboard event QKeyEvent, mouse event QMouseEvent, and timer event QTimerEvent, etc. The inheritance relationship diagram with the QEvent class is shown below. This chapter will explain these three common events in detail, and will also involve the knowledge of event filters and custom events. For the relevant content of this chapter, you can view it through the keyword The Event System in the Qt help.

 

2. Events in Qt

An event is a general term for events or actions that are generated internally or externally by various applications that need to be known. An object is used in Qt to represent an event, inherited from the QEvent class.

It should be noted that events are not the same as signals. For example, if you click a button on the interface, the mouse event QMouseEvent (not generated by the button) will be generated, and because the button is pressed, it will send out clicked() Click signal (generated by the button). Generally, only the click signal of the button is concerned here, and the mouse event is not considered, but if you want to design a button, or make it produce other effects when the button is clicked, then you must care about the mouse event. It can be seen that events and signals are two different levels of things, with different senders and different functions. In Qt, any QObject subclass instance can receive and process events.

2.1 Event processing

An event is represented by a specific QEvent subclass, but sometimes an event contains multiple event types. For example, mouse events can be divided into multiple operations such as mouse press, double-click, and move. These event types are represented by the enumeration type QEvent::Type of the QEvent class, which contains more than one hundred event types, which can be viewed in the help document of the QEvent class. Although a subclass of QEvent can represent an event, it cannot be used to handle an event, so how should an event be handled? In the help documentation of the notify() function of the QCoreApplication class, five methods of handling events are given:

  • Method 1: Reimplement event processing functions such as paintEvent() and mousePressEvent() of the component. This is the most commonly used method, but it can only be used to handle specific events of specific components.
  • Method 2: Reimplement the notify() function. This function is powerful and provides complete control to get events before the event filter gets them. However, it can only handle one event at a time.
  • Method 3: Install an event filter on the QApplication object. Because a program has only one QApplication object, the function realized in this way is the same as using the notify() function, and the advantage is that multiple events can be processed at the same time.
  • Method 4: Reimplement the event() function. The event() function of the QObject class can get the event before it reaches the default event handler.
  • Method five: Install an event filter on the object. Event filters can be used to handle different events of different sub-components in one interface class at the same time.

In actual programming, method one is the most commonly used, followed by method five. Because the second method needs to inherit from the QApplication class; and the third method needs to use a global event filter, which will slow down the transmission of events, so although these two methods are very powerful, they are rarely used.

The benefits of this article, free to receive Qt development learning materials package, technical video, including (C++ language foundation, introduction to Qt programming, QT signal and slot mechanism, QT interface development-image drawing, QT network, QT database programming, QT project combat, QSS, OpenCV, Quick module, interview questions, etc.) ↓↓↓↓↓↓See below↓↓Click on the bottom of the article to receive the fee↓↓

2.2 Delivery of events

At the end of the main() function of each program, the exec() function of the QApplication class will be called, which will make the Qt application enter the event loop, so that the application can receive various events that occur during runtime. Once an event occurs, Qt will construct a corresponding QEvent subclass object to represent it, and then pass it to the corresponding QObject object or its subobjects. Let's take a look at the event delivery process in Qt through an example .

Create a new Qt Gui application, the project name is myEvent, the base class is QWidget, and the class name remains Widget. After the establishment is complete, add a new file to the project, select the C++ class as the template, the class name is MyLineEdit, manually fill in the base class as QLineEdit, and customize a MyLineEdit class.

mylineEdit.h file:

#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H

#include <QLineEdit>

class MyLineEdit : public QLineEdit
{
    Q_OBJECT
public:
    explicit MyLineEdit(QWidget *parent = nullptr);
    
    // event()函数获取事件的类型
	bool event(QEvent *event);    

protected:
    // MyLineEdit类的键盘按下事件
    void keyPressEvent(QKeyEvent *event);
};

#endif // MYLINEEDIT_H

The declarations of the keyPressEvent() function and the event() function are added here.

mylineEdit.cpp file:

#include "mylineedit.h"
#include <QKeyEvent>
#include <QDebug>

MyLineEdit::MyLineEdit(QWidget *parent) :
    QLineEdit(parent)
{

}

// MyLineEdit类的键盘按下事件
void MyLineEdit::keyPressEvent(QKeyEvent *event)
{
    qDebug() << tr("MyLineEdit键盘按下事件");
    // 让MyLineEdit输入栏能输入字符
    QLineEdit::keyPressEvent(event);          // 执行QLineEdit类的默认事件处理
    event->ignore();                          // 忽略该事件
}

//event()函数获取事件的类型
bool MyLineEdit::event(QEvent *event)  
{
    // 判断触发事件类型是否为键盘按下事件
    if(event->type() == QEvent::KeyPress)
        qDebug() << tr("MyLineEdit的event()函数");
    return QLineEdit::event(event);   // 执行QLineEdit类event()函数的默认操作
}

Here, a MyLineEdit class is customized, which inherits from QWidget, and implements the keyPressEvent() function and event() function of the MyLineEdit class. event() function uses event->type() to get the type of event. If it is a keyboard press event QEvent::KeyPress, it will output information and return the operation result of the event() function of the parent class.

widget.h file:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
class MyLineEdit;
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

	// Widget类的事件过滤器
    bool eventFilter(QObject *obj, QEvent *event);    

private:
    Ui::Widget *ui;
    MyLineEdit *lineEdit;

protected:
    // Widget类的键盘按下事件
    void keyPressEvent(QKeyEvent *event);
};

#endif // WIDGET_H

The declaration of the keyPressEvent() function is also added here.

widget.cpp file:

#include "widget.h"
#include "ui_widget.h"
#include "mylineedit.h"
#include <QKeyEvent>
#include <QDebug>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
        
    lineEdit = new MyLineEdit(this);
    lineEdit->move(100, 100);
}

Widget::~Widget()
{
    delete ui;
}

// Widget类的键盘按下事件
void Widget::keyPressEvent(QKeyEvent *event)
{
    qDebug() << tr("Widget键盘按下事件");
}

// Widget类的事件过滤器
bool Widget::eventFilter(QObject *obj, QEvent *event) // 事件过滤器
{
    // 如果是lineEdit部件上的事件
    if(obj == lineEdit)
    {              
        if(event->type() == QEvent::KeyPress)
            qDebug() << tr("Widget的事件过滤器");
    }
    return QWidget::eventFilter(obj, event);
}

The keyPressEvent() function of the Widget class is also implemented here, and the keyPressEvent() function of the MyLineEdit class will be called. In the event filter, first judge whether the object of the event is lineEdit, if so, then judge the event type, and finally return the execution result of the default event filter of the QWidget class.

Run the program, and then press any key on the keyboard, for example, press the a key here, the execution result is shown in the figure below.

 

It can be seen that the order of event delivery is as follows: first the event filter, then the event() function of the focus component, and finally the event handler of the focus component, such as the keyboard press event function here; if the focus component ignores The event, then the event processing function of the parent component will be executed, as shown in the figure above. Note that the event() function and event processing function are redefined within the component, while the event filter is defined in the parent component of the component.

The benefits of this article, free to receive Qt development learning materials package, technical video, including (C++ language foundation, introduction to Qt programming, QT signal and slot mechanism, QT interface development-image drawing, QT network, QT database programming, QT project combat, QSS, OpenCV, Quick module, interview questions, etc.) ↓↓↓↓↓↓See below↓↓Click on the bottom of the article to receive the fee↓↓ 

Guess you like

Origin blog.csdn.net/QtCompany/article/details/131743397