Qt--事件分发器

写在前面

在 Qt 中,事件分发器(Event Dispatcher)是一个核心概念,用于处理 GUI 应用程序中的事件。事件分发器负责将事件从一个对象传递到另一个对象,直到事件被处理或被取消。

每个继承自QObject或QObject的类都可以在本类中重写bool event(QEvent *e),来实现相关事件的捕获和拦截。

事件分发器的工作原理

event函数

每个继承自QObject或QObject的类都可以在本类中重写bool event(QEvent *e),来实现相关事件的捕获和拦截,原型如下:

bool event(QEvent *e);

e: 存储事件相关信息
返回值:返回true表示拦截处理,不再向下分发

这里使用一个简单的示例图帮助理解:
Qt--事件分发器_第1张图片
我们知道,没有application应用程序运行后,都有一个事件循环,即exec()。

每个事件都会有一个“四元组”标识事件来自哪个对象,哪个事件触发(信号),要发往哪个对象,使用哪个函数(槽)处理。

而事件分发器则工作在信号发往目的对象的这一阶段,即某一控件对象收到来自事件循环的某一需要该对象处理的事件(信号)时,就会进入到事件分发器,在事件分发器中,可以会有一些事件类型的判断,根据类型进行相应的处理(分发)。

例,在事件分发器中判断,若是鼠标按下事件,则使用mouPressEvent进行专门处理,若是鼠标移动事件,则使用mouseMoveEvent进行相应处理。

可以这样理解:

bool QLabel::event(QEvent* e)
{
	if (是鼠标按下事件)
	{
		//调用mousePressEvent处理,mousePressEvent是虚函数,会动态调用对应版本
		mousePressEvent();
		return true;		//返回true表示成功拦截处理
	}
	else if (鼠标移动事件)
	{
		//同理,调用mouseMoveEvent虚函数进行相应处理
		mouseMoveEvent();
		return true;
	}

	//也可以继续分发给父类处理
	return QFrame::event(e);
}

示例

这里在一个自定义的Label控件中拦截鼠标按下事件:

#ifndef MYLABEL_H
#define MYLABEL_H

#include >

class MyLabel : public QLabel
{
    Q_OBJECT
public:
    explicit MyLabel(QWidget *parent = nullptr);

    //重写鼠标相关事件
    void enterEvent(QEnterEvent *event);

    void leaveEvent(QEvent *event);

    void mousePressEvent(QMouseEvent *ev);
    void mouseReleaseEvent(QMouseEvent *ev);
    void mouseMoveEvent(QMouseEvent *ev);

    //事件分发器
    bool event(QEvent *e);

signals:

};

#endif // MYLABEL_H

#include "mylabel.h"
#include 
#include 
#include 

MyLabel::MyLabel(QWidget *parent)
    : QLabel{parent}
{
    //设置鼠标追踪
    setMouseTracking(true);
}

//重写鼠标相关事件
void MyLabel::enterEvent(QEnterEvent *event)
{
    qDebug() << "鼠标进入";
}

void MyLabel::leaveEvent(QEvent *event)
{
    qDebug() << "鼠标离开";
}



void MyLabel::mousePressEvent(QMouseEvent *ev)
{
    //if (ev->button() == Qt::LeftButton)
    {
        QString qs = QString("鼠标按下, x = %1, y = %2").arg(ev->x()).arg(ev->y());
        qDebug() << qs;
    }

}

void MyLabel::mouseReleaseEvent(QMouseEvent *ev)
{
    qDebug() << "鼠标释放";
}

void MyLabel::mouseMoveEvent(QMouseEvent *ev)
{
    //移动需要用buttons函数,位与判断
    if (ev->buttons() & Qt::LeftButton)
    {
        QString qs = QString("鼠标移动了, x = %1, y = %2").arg(ev->x()).arg(ev->y());
        qDebug() << qs;
    }

}

//事件分发器
bool MyLabel::event(QEvent *e)
{
    if (e->type() == QEvent::MouseButtonPress)
    {
        qDebug() << "event 拦截鼠标按下事件";
        return true;
    }

    return QLabel::event(e);
}


运行可以看到成功在event中拦截到鼠标按下事件,而不再继续分发调用mousePressEvent:
拦截鼠标按下事件

你可能感兴趣的:(QT,C++,qt,开发语言)