Qt event loop mechanism

Original: https://blog.csdn.net/simonyucsdy/article/details/82749539

Question 1: Qt common event What?

A: mouse events (QMouseEvent), keyboard events (QKeyEvent), draw event (QPaintEvent), window size change (QResizeEvent), scroll events (QScrollEvent), control displays (QShowEvent), controls hidden (QHideEvent), the timer event (QTimerEvent )and many more. .

Question 2: Qt is event-driven, how to understand this sentence it?

Qt converts the signal (software interrupt) generated by the system to Qt events, and events packaged as such, all of the event classes are derived from the QEvent, event production and processing is the spindle Qt program, and along with the entire program Operation cycle. So we say, Qt is event-driven.

Question 3: Qt event is generated by whom? Qt is how the signal is converted into an event?

A: The official manual of Qt said the incident from two sources: external programs and internal procedures, in most cases from the operating system and the function returns true by spontaneous () event to learn from external programs, indicating when the spontaneous () returns false events from inside the program, like the routines 1 create an event and distributing it out.

Question 4: Qt event is received by whom?

A: QObject! It is the base class for all Qt classes! Qt is the core object model! One of the three core functions which QObject class is: event processing. QObject by event () function call to get the event. All classes required to handle the event must inherit from Qobject, it can be re-defined event () function to implement a custom event handler or event to the parent.

Question 5: Process event handling is what?

A: The important point is different from the signal event: The event is a class object has a specific type, at an event in most cases is distributed to a queue (event queue), when there is a queue of non-stop events in the queue the event is sent to QObject object, when the queue is empty when it is blocked waiting for an event, this process is the event loop !

QCoreApplication :: exec () opens this cycle until QCoreApplication :: exit () is called before the termination, so that Qt event loop is accompanied by a program of the entire operation cycle!

Another case is the synchronization processing () to send events through sendEvent out, and the processing flow directly into the transfer event.

Event processing is as shown:

img

Routine 1: sendEvent synchronized event distribution

/*!
 * \brief Widget::Widget 使用sendEvent同步分发事件
 * 使用QPushButton模拟键盘的回删和向前删除按键
 * \param parent
 */
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::on_button_back_clicked()
{
    int key = Qt::Key_Backspace; //
 
    QKeyEvent EventPress(QEvent::KeyPress, key, Qt::NoModifier);
    QApplication::sendEvent(ui->textEdit, &EventPress);
 
    QKeyEvent EventRelease(QEvent::KeyRelease, key, Qt::NoModifier);
    QApplication::sendEvent(ui->textEdit, &EventRelease);
}
 
void Widget::on_button_delete_clicked()
{
    int  key = Qt::Key_Delete; //
 
    QKeyEvent EventPress(QEvent::KeyPress, key, Qt::NoModifier);
    QApplication::sendEvent(ui->textEdit, &EventPress);
 
    QKeyEvent EventRelease(QEvent::KeyRelease, key, Qt::NoModifier);
    QApplication::sendEvent(ui->textEdit, &EventRelease);
}

PostEvent relations and relations sendEvent like Qt :: QueuedConnection and Qt :: DirectConnection, only the first two post-distribution event is to send a message both fills the mechanism postEvent and QueuedConnected is asynchronous communication, while the other two are synchronized communication.

img

Routine 2: postEvent asynchronous event distribution

int count = 0;
 
/*!
 * \brief Widget::Widget 使用postEvent异步分发事件
 * 连续分发10个事件,在事件处理函数中逐个处理
 * \param parent
 */
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
 
    int i = 1;
    while(i <= 10)
    {
        //postEvent传递的事件必须是通过new创建的
        qDebug() << "分发第" << i << "个事件";
        QApplication::postEvent(this, new QEvent(NewType));
        i++;
    }
}
 
void Widget::customEvent(QEvent *event)
{
    //使用延时模拟处理过程
    if(event->type() == NewType)
    {
        qDebug() << "现在时间:" <<
                    QTime::currentTime().toString("hh::mm:ss.zzz");
        qDebug() << "第" << ++count << "次收到了事件!处理事件需要一点时间!";
        Delay(1000*2);
    }
 
    QWidget::customEvent(event);
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::Delay(unsigned int msec)
{
    QTime start = QTime::currentTime();
 
    QTime end;
    do{
        end = QTime::currentTime();
    } while(start.msecsTo(end) <= msec);
}

Question 6: Event filter mechanism?

A first transfer station and a processing flow event is an event filter eventFilter (), an object A to another object B can install event handlers, or monitor to achieve the object B interception function event. We can give the listener named A, B named receiver. An object can monitor multiple objects, an object can also monitor multiple events. Event filter returns true, said the event has been processed, or passed to the next listener or the receiver itself.

img

Routine 3: Event Filter

/*!
 * \brief Widget::Widget 事件过滤器
 * 不借助Tab键的情况下使用Space键实现控件跳转
 * \param parent
 */
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
 
    ui->lineEdit_user->setText(QString("lee"));
    focusNextChild();
    ui->lineEdit_password->setText(QString("*******"));
 
    //监听控件
    ui->lineEdit_user->installEventFilter(this);
    ui->lineEdit_password->installEventFilter(this);
    ui->button_accept->installEventFilter(this);
    ui->button_cancel->installEventFilter(this);
}
 
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    //定义事件处理动作
    if (watched == ui->lineEdit_user || watched == ui->lineEdit_password
        || watched == ui->button_accept || watched == ui->button_cancel)
    {
        if (event->type() == QEvent::KeyPress)
        {
            QKeyEvent *e = static_cast<QKeyEvent *>(event);
            if(e->key() == Qt::Key_Space)
            {
                focusNextChild();
                return true;
            }
        }
    }
    return QWidget::eventFilter(watched, event);
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::on_button_cancel_clicked()
{
    qApp->quit();
}

* A point worth noting is responsible for QCoreApplication While the event distribution, but is itself inherited from QObject, so in the event prior to distribution, but also check whether other objects installed itself an event filters, event filters may filter out some of the events not released. *

Routine 4: QCoreApplication install an event filter

widget.cpp

/*!
 * \brief Filter::eventFilter 用于监听qApp的监听器
 * \return
 */
bool Filter::eventFilter(QObject *obj, QEvent *event)
{
    //阻止所有的鼠标点击事件
    if(event->type() == QEvent::MouseButtonPress)
    {
        qDebug() << "sorry everybody, I gonna filter all the mouse event!";
        return true;
    }
    return QObject::eventFilter(obj,event);
}
 
/*!
 * \brief Widget::Widget
 * \param parent
 */
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "mouse press!";
 
    QWidget::mousePressEvent(event);
}

main.c

#include "widget.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
 
    Filter filter;
    a.installEventFilter(&filter);
 
    Widget w;
    w.show();
 
    return a.exec();
}
————————————————
版权声明:本文为CSDN博主「ingy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/simonyucsdy/article/details/82749539

Can (), custom processing operation of the event by re-implementing the QCoreApplication notify.

Routine 5: QCoreApplication subclass and override notify

newapplication.h

#ifndef NEWAPPLICATION_H
#define NEWAPPLICATION_H
 
#include <QApplication>
 
class NewApplication : public QApplication
{
public:
    NewApplication(int argc, char **argv) : QApplication(argc,argv) {}
 
    virtual bool notify(QObject *, QEvent *);
 
};
 
#endif // NEWAPPLICATION_H
————————————————
版权声明:本文为CSDN博主「ingy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/simonyucsdy/article/details/82749539

newapplication.cpp

#include "newapplication.h"
#include <QMouseEvent>
#include <QDebug>
 
bool NewApplication::notify(QObject *receiver, QEvent *event)
{
    if(event->type() == QMouseEvent::MouseButtonPress)
    {
        qDebug() << "sorry everybody I gonna filter all the mouse press event";
        return true;
    }
 
    return QApplication::notify(receiver,event);
}
————————————————
版权声明:本文为CSDN博主「ingy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/simonyucsdy/article/details/82749539

widget.h

#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <QMouseEvent>
 
namespace Ui {
class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
 
protected:
    void mousePressEvent(QMouseEvent *event);
 
private slots:
    void on_pushButton_clicked();
 
private:
    Ui::Widget *ui;
};
 
#endif // WIDGET_H
————————————————
版权声明:本文为CSDN博主「ingy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/simonyucsdy/article/details/82749539

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "I am mainwindow Widget, I got a mouse event!";
 
    QWidget::mousePressEvent(event);
}
 
void Widget::on_pushButton_clicked()
{
    qDebug() << "I am push button , I got a mouse event!";
}
————————————————
版权声明:本文为CSDN博主「ingy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/simonyucsdy/article/details/82749539

main.cpp

#include "widget.h"
#include <QApplication>
#include "newapplication.h"
 
int main(int argc, char *argv[])
{
//    QApplication a(argc, argv);
    NewApplication a(argc, argv);
 
    Widget w;
    w.show();
 
    return a.exec();
}
————————————————
版权声明:本文为CSDN博主「ingy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/simonyucsdy/article/details/82749539

The result: Click anywhere on the interface, qApp events are filtered.

img

Summary: event-processing

1. The re-implement the object-specific event handler, e.g. mousePressEvent, keyPressEvent, showEvent etc., after the event has been processed to the parent;

2. reimplement event function is processed after the event to the parent;

3. Install an event filter on the object, so that other objects to control the behavior of this event object;

4. QCoreApplication mounted to the main event filter, before calling for notify event distribution, it determines the handling of events according to a filter (e.g.: discarded);

5. subclass QCoreApplication, reimplement notify event distribution function;

Question 7. how to use custom events?

Scenario: custom events for a particular operation is useful to define a continuous 10 mouse click events NewMouseEvent, 10 times in a row click on the screen, wake up the screen calibration procedure.

Custom Event

newmouseevent.h

#ifndef MYEVENT_H
#define MYEVENT_H
 
#include <QEvent>
#include <QString>
 
class NewMouseEvent : public QEvent
{
public:
    explicit NewMouseEvent() :  QEvent(MouseTenClick) {}
    const static Type MouseTenClick = static_cast<Type>(QEvent::User+0x10);
};
 
#endif // MYEVENT_H
————————————————
版权声明:本文为CSDN博主「ingy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/simonyucsdy/article/details/82749539

widget.h

#ifndef MYEVENT_H
#define MYEVENT_H
 
#include <QEvent>
#include <QString>
 
class NewMouseEvent : public QEvent
{
public:
    explicit NewMouseEvent() :  QEvent(MouseTenClick) {}
    const static Type MouseTenClick = static_cast<Type>(QEvent::User+0x10);
};
 
#endif // MYEVENT_H
————————————————
版权声明:本文为CSDN博主「ingy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/simonyucsdy/article/details/82749539

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include "newmouseevent.h"
#include <QMouseEvent>
#include <QTimer>
 
/*!
 * \brief Widget::Widget
 * 创建并分发一种新的事件:鼠标连续点击10次
 * \param parent
 */
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
 
    ui->label->installEventFilter(this);
 
    ui->label->setText(tr("请连续点击屏幕以唤醒屏幕校准功能!"));
    ui->label->adjustSize();
 
    m_timer = new QTimer;
    m_timer->setInterval(1000);
    m_timer->start();
    connect(m_timer, SIGNAL(timeout()), SLOT(clearCount()));
 
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::mousePressEvent(QMouseEvent *event)
{
    QWidget::mousePressEvent(event);
}
 
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() != Qt::LeftButton)
        return;
 
    if(m_timer->isActive())
        m_timer->stop(); //如果计时器在运行,则停止然后重新开始
    m_timer->start();
 
    count++;
 
    if(10 == count)
    {
        count = 0;
 
        NewMouseEvent event;
        qApp->sendEvent(ui->label, &event);
    }
 
    QWidget::mouseReleaseEvent(event);
}
 
bool Widget::eventFilter(QObject *obj, QEvent *event)
{
    if(obj == ui->label && event->type()== NewMouseEvent::MouseTenClick)
    {
        ui->label->setText(tr("你连续点击了10次屏幕,校准程序正在启动!"));
        ui->label->adjustSize();
        return true;
    }
 
    return QWidget::eventFilter(obj,event);
}
 
void Widget::clearCount()
{
    count = 0;
}
————————————————
版权声明:本文为CSDN博主「ingy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/simonyucsdy/article/details/82749539

operation result

Click the mouse 10 consecutive times counted once a custom event

img

img

Question 8: recipient of the object is deleted halfway what happens? The listener is deleted What happens?

Failed to send? program crash?

widget.h

#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <QLabel>
 
namespace Ui {
class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
 
protected:
 
private slots:
    void slotSendEvent();
    void deleteLabel();
 
private:
    Ui::Widget *ui;
 
    QLabel *m_label;
 
};
 
#endif // WIDGET_H
————————————————
版权声明:本文为CSDN博主「ingy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/simonyucsdy/article/details/82749539

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QTimer>
#include <QResizeEvent>
#include <QDebug>
 
/*!
 * \brief Widget::Widget
 * 在事件循环分发事件给接收者之前,接收者被删除
 * \param parent
 */
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
 
    //创建小窗口
    m_label = new QLabel(this);
    m_label->setStyleSheet(QString("border:1px solid red;"));
    m_label->setGeometry(QRect(0,0,200,100));
 
    //在qApp发送事件之前销毁小窗口
    QTimer::singleShot(1000, this, SLOT(deleteLabel()));
    //qApp发送事件给小窗口
    QTimer::singleShot(2000, this, SLOT(slotSendEvent()));
 
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::slotSendEvent()
{
    QResizeEvent re(QSize(300,200), QSize(200,100));
 
    qDebug() << "qApp发送了一个事件给小窗口!";
    qApp->sendEvent(m_label, &re);
}
 
void Widget::deleteLabel()
{
    qDebug() << "小窗口被销毁了!";
    delete m_label;
    m_label = NULL;
}
————————————————
版权声明:本文为CSDN博主「ingy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/simonyucsdy/article/details/82749539

operation result

img

Guess you like

Origin www.cnblogs.com/schips/p/12536411.html