Qt事件处理机制3-事件函数的分发

Qt开发中,经常重写event函数和具体的事件处理函数,例如mousePressEvent、paintEvent等,那么这些具体的事件处理函数是怎样被调用的呢?答案是由继承自QObject的类中的event函数来处理事件分发。这里以间接继承自QWidget的派生类MyButton举例说明。

MyButton.h

cpp 复制代码
#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QPushButton>

class MyButton : public QPushButton
{
    Q_OBJECT
public:
    MyButton(QWidget *parent = nullptr);
    ~MyButton();

protected:
    bool event(QEvent *e) override;
    void mousePressEvent(QMouseEvent *event) override;
};

#endif // MYBUTTON_H

MyButton.cpp

cpp 复制代码
#include "MyButton.h"
#include <QDebug>
#include <QEvent>
#include <QMouseEvent>
MyButton::MyButton(QWidget *parent) : QPushButton(parent)
{

}

MyButton::~MyButton()
{

}

bool MyButton::event(QEvent *e)
{
    if (e->type() == QEvent::MouseButtonPress)
    {
        qDebug() << __FUNCTION__ << e->isAccepted();
    }

    return QPushButton::event(e);
}

void MyButton::mousePressEvent(QMouseEvent *event)
{
    qDebug() << __FUNCTION__ << event->isAccepted();
}

MainWindow.h

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    bool event(QEvent *e) override;
    void mousePressEvent(QMouseEvent *event) override;

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

MainWindow.cpp

cpp 复制代码
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QDebug>
#include <QEvent>
#include <QMouseEvent>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

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

bool MainWindow::event(QEvent *e)
{
    if (e->type() == QEvent::MouseButtonPress)
    {
        qDebug() << __FUNCTION__ << e->isAccepted();
    }

    return QMainWindow::event(e);
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    qDebug() << __FUNCTION__ << event->isAccepted();
}

运行结果正常

cpp 复制代码
MyButton::event true
MyButton::mousePressEvent true

// 若如下修改MyButton::mousePressEvent函数
void MyButton::mousePressEvent(QMouseEvent *event)
{
    qDebug() << __FUNCTION__ << event->isAccepted();
    event->ignore();
}
那么运行结果为(该代码同时验证了上一篇文章所说的事件函数的传播):
MyButton::event true
MyButton::mousePressEvent true
MainWindow::event true
MainWindow::mousePressEvent true

可以看到,QPushButton::event(e)函数里最终调用了具体事件处理函数mousePressEvent,该函数是在QWidget类的event函数中进行分发的(MyButton->QPushButton->QAbstractButton->QWidget层层调用event函数)。

补充:QWidget中,event函数主要负责事件分发

cpp 复制代码
bool QWidget::event(QEvent *event)
{
	Q_D(QWidget);

    // ignore mouse and key events when disabled
    if (!isEnabled()) {
        switch(event->type()) {
        case QEvent::TabletPress:
        case QEvent::TabletRelease:
        case QEvent::TabletMove:
        case QEvent::MouseButtonPress:
        case QEvent::MouseButtonRelease:
        case QEvent::MouseButtonDblClick:
        case QEvent::MouseMove:
        case QEvent::TouchBegin:
        case QEvent::TouchUpdate:
        case QEvent::TouchEnd:
        case QEvent::TouchCancel:
        case QEvent::ContextMenu:
        case QEvent::KeyPress:
        case QEvent::KeyRelease:
#if QT_CONFIG(wheelevent)
        case QEvent::Wheel:
#endif
            return false;
        default:
            break;
        }
    }
    
	switch (event->type()) {
    case QEvent::MouseMove:
        mouseMoveEvent((QMouseEvent*)event);
        break;

    case QEvent::MouseButtonPress:
        mousePressEvent((QMouseEvent*)event);
        break;

    case QEvent::MouseButtonRelease:
        mouseReleaseEvent((QMouseEvent*)event);
        break;

    case QEvent::MouseButtonDblClick:
        mouseDoubleClickEvent((QMouseEvent*)event);
        break;
    ...
        default:
        return QObject::event(event);
    }
    return true;
}
相关推荐
xlp666hub3 小时前
Leetcode第七题:用C++解决接雨水问题
c++·leetcode
肆忆_4 小时前
实战复盘:手写 C++ 虚拟机的高性能并行 GC (Thread Pool + Work Stealing)
c++
肆忆_4 小时前
虚函数进阶答疑:把上一篇博客评论区里最容易卡住的问题,一次追到底
c++
saltymilk21 小时前
使用 C++ 模拟 ShaderLanguage 的 swizzle
c++·模板元编程
xlp666hub1 天前
Leetcode第五题:用C++解决盛最多水的容器问题
linux·c++·leetcode
得物技术1 天前
搜索 C++ 引擎回归能力建设:从自测到工程化准出|得物技术
c++·后端·测试
xlp666hub2 天前
Leetcode 第三题:用C++解决最长连续序列
c++·leetcode
会员源码网2 天前
构造函数抛出异常:C++对象部分初始化的陷阱与应对策略
c++
xlp666hub2 天前
Leetcode第二题:用 C++ 解决字母异位词分组
c++·leetcode
不想写代码的星星2 天前
static 关键字:从 C 到 C++,一篇文章彻底搞懂它的“七十二变”
c++