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;
}
相关推荐
yuyanjingtao11 分钟前
CCF-GESP 等级考试 2025年9月认证C++一级真题解析
c++·青少年编程·gesp·csp-j/s
xzk2012100222 分钟前
洛谷 P1438 无聊的数列 题解
c++·算法·树状数组
00后程序员张25 分钟前
C++ string 类使用攻略
开发语言·c++
OKkankan28 分钟前
list的使用和模拟实现
数据结构·c++·算法·list
keep intensify1 小时前
Redis基础指令全解析:从入门到精通
linux·数据库·c++·redis
爱吃生蚝的于勒1 小时前
【Linux】零基础学会linux环境基础开发工具使用(yum,vim,makefile,gdb)
linux·服务器·数据结构·c++·蓝桥杯·编辑器·vim
R-G-B1 小时前
【34】MFC入门到精通——MFC 控件 ComboBox 运行点击控件下拉框 “终止“、“重试“、“忽略“、“引发异常”
c++·mfc·combobox“引发异常”·“终止“·“重试“·“忽略“·“引发异常”
零基础的修炼1 小时前
Linux---线程封装
linux·c++·算法
给大佬递杯卡布奇诺2 小时前
FFmpeg 基本API avio_read函数内部调用流程分析
c++·ffmpeg·音视频
liulilittle2 小时前
Y组合子剖析:C++ 中的递归魔法
开发语言·c++·编程语言·函数式编程·函数式·函数编程·y组合子