Qt基础学习之事件
Qt-事件
1. Qt对事件的描述及分类
什么是事件
事件是由程序内部或者外部产生的事件或某种动作的统称。比如鼠标点击产生一鼠标事件,键盘按下产生一个键盘事件,窗口显示产生一个绘图事件等。事件通常是来自于底层的窗口系统,当然也可以手动发送自定义的事件,事件不同于信号,他既可以是同步的,也可以使一异步的,这取决于是使用sendEvent()还是postEvent()发送的事件。并且事件支持过滤,这在事件的处理和传递上是具有很大好处。Qt使用QEvent()及其子类处理事件,比如,QMoustEvent()处理与鼠标相关的事件。
事件的分类
- 根据事件的来源和传递分类
- 自发事件:这些事件是由窗口系统生成,置于系统队列中,并在事件循环中一个一个处理。
- 发布的事件:这些事件由Qt和应用程序产生,并有Qt排队,经事件循环处理。
- 发送的事件:这些事件由Qt和应用程序产生,并直接发送到目标对象,不由事件循环处理。
- 事件的细分类型
事件的细分类型由QEvent中的枚举常量表示,比如鼠标事件QMouseEvent具有双击、移动、按下事件,这些事件可以使用MouseButtonDblClick、MouseMove、MouseButtonPress枚举常量表示。不同的事件表示方式可以通过 Type QEvent::type() const函数来获取。
事件继承
事件的传递和处理
基本规则
目标对象如果没有处理事件,那么事件会传递给父对象,如果父对象依然没有处理,再传递给爷爷对象。直到事件别处理处理或者到达顶层对象为止。
事件传递过程
- 第一步: Qt中的事件循环,从可能产生事件的地方捕获事件,并把事件转化为带有事件信息的对象。然后由事件处理流程发送给需要处理事件的对象来处理事件。
- 第二步:Qt调用QCoreApplication::notify()函数对事件进行分发。
- 第三步:QObject对象调用QObject::event()函数接收事件。
- 第四步:event()函数根据事件的类型,调用对应的事件处理函数,如果返回true,则表示事件被处理,否则需要进一步传递或者丢弃。
事件处理流程图
事件处理
任何QObject子类都可以处理事件,QEvent及其子对象描述事件信息,但是并不对事件进行处理。真正处理事件的是类的成员函数,通常称为事件处理函数。Qt已经为绝大多数事件提供了事件处理函数,并做了默认处理。这些默认的事件处理函数通过event()进行调用,如果默认事件处理函数不能满足要求,可以重新event()函数实现。
QWidget::event()实现
事件处理的五种方式
- 重写默认事件处理函数
- 重写QObect::event()函数,事件在到达事件处理函数之前,先被event()函数捕获,对未被明确定义的事件处理,需要调用父类的event()函数处理。
- 在QObject()对象上安装事件过滤器,对象一旦通过installEventFilter()函数注册,所有传递给目标对象的事件都会先别监视对象的eventFilter()捕获,如果监视对象安装了多个事件过滤器,会按照逆序方式一次激活。
- 在QApplication上安装事件过滤器,这与重新实现noitify一样强大。一旦在QApplication上注册了事件过滤器,那么每一对象每一个事件都会在发送到其他事件过滤器之前,发送到这个eventFilter()函数。
- 重写QCoreApplication::notify()函数。
事件处理方式实例
点击查看代码
#include "widget.h"
#include <QApplication>
#include <QDebug>
class A : public QWidget
{
bool event(QEvent *e){
if(e->type() == QEvent::KeyPress){
qDebug() << "key press" << endl;
}
return QWidget::event(e);
}
void mousePressEvent(QMouseEvent *e){
qDebug() << "mouse press" << endl;
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
A ma;
ma.resize(300,200);
ma.show();
return a.exec();
}
事件传递实例
点击查看代码
class A : public QWidget {
bool event(QEvent *e){
switch (e->type()) {
case QEvent::KeyPress:
qDebug() << "parent" <<"key press";
break;
case QEvent::MouseButtonPress:
qDebug() << "parent" << "mouse press" <<endl;
break;
case QEvent::MouseButtonRelease:
qDebug() << "parent" << "mouse release" << endl;
break;
default:
break;
}
return QWidget::event(e);
}
};
class C : public QPushButton {
bool event(QEvent *e){
if(e->type() == QEvent::KeyPress){
qDebug() << "key press" << endl;
return 0;
}
if(e->type() == QEvent::MouseButtonPress){
qDebug()<< "mouse press" <<endl;
return 1;
}
return QWidget::event(e);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
A ma;
C *mc = new C();
mc->setParent(&ma);
mc->setText("btn");
mc->move(20,20);
ma.resize(200,300);
ma.show();
return a.exec();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能