QObject事件入口,所有事件的处理入口都是QObject::event和其子类的event函数
bool MyQObject::event(QEvent *e){
//处理不同的事件
......
//处理不了的传给父对象处理
return QObject::event(e);
}
bool QObject::event(QEvent *e)
{
switch (e->type()) {
case QEvent::Timer: //startTimer函数触发的QTimerEvent,最终走timerEvent函数处理
timerEvent((QTimerEvent*)e);
break;
case QEvent::ChildAdded:
case QEvent::ChildPolished:
case QEvent::ChildRemoved:
childEvent((QChildEvent*)e);
break;
case QEvent::DeferredDelete:
qDeleteInEventHandler(this);
break;
case QEvent::MetaCall: //发送信号触发关联的槽函数时(非直接调用模式),最终走QEvent::MetaCall事件调到对应的函数
{
QAbstractMetaCallEvent *mce = static_cast<QAbstractMetaCallEvent*>(e);
if (!d_func()->connections.loadRelaxed()) {
QBasicMutexLocker locker(signalSlotLock(this));
d_func()->ensureConnectionData();
}
QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId());
mce->placeMetaCall(this);//调用对应的函数
break;
}
case QEvent::ThreadChange: {
Q_D(QObject);
QThreadData *threadData = d->threadData.loadRelaxed();
QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.loadRelaxed();
if (eventDispatcher) {
QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(this);
if (!timers.isEmpty()) {
// do not to release our timer ids back to the pool (since the timer ids are moving to a new thread).
eventDispatcher->unregisterTimers(this);
QMetaObject::invokeMethod(this, "_q_reregisterTimers", Qt::QueuedConnection,
Q_ARG(void*, (new QList<QAbstractEventDispatcher::TimerInfo>(timers))));
}
}
break;
}
default:
if (e->type() >= QEvent::User) {
customEvent(e);
break;
}
return false;
}
return true;
}
给对象安装一个事件过滤器即filterObj对象。
当触发事件时首先调用filterObj的eventFilter函数,判断是否过滤此事件
如果事件需要被过滤,eventFilter()函数必须返回true;否则它必须返回false。
如果在单个对象上安装了多个事件筛选器,则首先激活最后安装的筛选器。
void QObject::installEventFilter(QObject *obj)
{
Q_D(QObject);
if (!obj)
return;
//obj必须和当前对象在同一线程才能添加成功
if (d->threadData != obj->d_func()->threadData) {
qWarning("QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
return;
}
if (!d->extraData)
d->extraData = new QObjectPrivate::ExtraData;
// clean up unused items in the list
d->extraData->eventFilters.removeAll((QObject*)nullptr);
d->extraData->eventFilters.removeAll(obj);
//这里调用prepend将事件过滤器添加到最前面
d->extraData->eventFilters.prepend(obj);
}
事件的处理流程就是先调用各种过滤函数,判断是否过滤,不过滤才会走到event()函数
eventFilter就是其中的一种过滤函数
返回true表示需要过滤,事件会终止不会执行
返回false表示不过滤,会继续传递事件,走到调用event()函数处理
eventFilter主要配合installEventFilter使用
eventFilter函数并不是给自己用的,正常使用一般是继承QObject实现eventFilter函数作为过滤器使用,安装在其他对象上面,帮助其他对象过滤事件
默认实现,直接返回false,表示不过滤任何事件
bool QObject::eventFilter(QObject * watched, QEvent * event )
{
return false;
}
事件的处理流程
bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
{
//先走全局app的事件过滤函数sendThroughApplicationEventFilters
//QCoreApplication存在并且接收者在主线程中的才会走app的全局过滤函数
if (QCoreApplication::self
&& receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()
&& QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
filtered = true;
return filtered;
}
// 再调用接收者安装事件过滤器的eventFilter函数,返回true将不会继续往下走调到event
if (sendThroughObjectEventFilters(receiver, event)) {
filtered = true;
return filtered;
}
//调用event函数处理事件
consumed = receiver->event(event);
return consumed;
}
全局app的事件过滤函数
bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
{
//不能在主线程之外访问应用程序(app)的事件过滤器
Q_ASSERT(receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread());
if (extraData) {
// 应用程序事件过滤器只对GUI线程中的对象调用
for (int i = 0; i < extraData->eventFilters.size(); ++i) {
QObject *obj = extraData->eventFilters.at(i);
if (!obj)
continue;
//过滤器和接收者不在同一线程,直接continue
if (obj->d_func()->threadData != threadData) {
qWarning("QCoreApplication: Application event filter cannot be in a different thread.");
continue;
}
//调用过滤器的eventFilter函数进行过滤处理,如果返回true直接退出,不需要继续处理
if (obj->eventFilter(receiver, event))
return true;
}
}
return false;
}
//调用接收者的事件过滤器进行过滤
bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, QEvent *event)
{
if (receiver != QCoreApplication::instance() && receiver->d_func()->extraData) {
//遍历接收者的事件过滤器函数,进行过滤
for (int i = 0; i < receiver->d_func()->extraData->eventFilters.size(); ++i) {
QObject *obj = receiver->d_func()->extraData->eventFilters.at(i);
if (!obj)
continue;
//过滤器和接收者不在同一线程,直接continue
if (obj->d_func()->threadData != receiver->d_func()->threadData) {
qWarning("QCoreApplication: Object event filter cannot be in a different thread.");
continue;
}
//调用过滤函数进行过滤
if (obj->eventFilter(receiver, event))//返回true将过滤事件
return true;
}
}
return false;
}
使用样例:
myobject.h
class myobject : public QObject
{
Q_OBJECT
public:
myobject(const QString &name, QObject *parent = nullptr):QObject(parent){
m_name = name;
}
virtual ~myobject(){};
private:
QString m_name;
protected:
virtual void childEvent(QChildEvent *event);
virtual bool eventFilter(QObject *watched, QEvent *event);
};
myobject.cpp
void myobject::childEvent(QChildEvent *event)
{
qDebug()<<"QChildEvent="<<event->type()<<objectName();
}
bool myobject::eventFilter(QObject *watched, QEvent *event)
{
qDebug()<<"eventFilter is"<<objectName()<<",event recver is"<<watched->objectName()<<",event is "<<event->type();
//return false; //测试返回false时不过滤事件
return true;//测试返回true时过滤事件
}
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
myobject *obj1= new myobject("boj1");
obj1->setObjectName("obj1");
myobject *obj2= new myobject("obj2");
obj2->setObjectName("obj2");
obj1->installEventFilter(obj2);//obj1事件会先走obj2的eventFilter函数,所以说这个eventFilter函数就不是给自己用的
obj2->setParent(obj1);//触发obj1的QEvent::ChildAdded
return a.exec();
}
myobject::eventFilter返回true时,运行输出:
eventFilter is "obj2" ,event recver is "obj1" ,event is QEvent::ChildAdded
myobject::eventFilter返回false时,运行输出:
eventFilter is "obj2" ,event recver is "obj1" ,event is QEvent::ChildAdded
QChildEvent= QEvent::ChildAdded "obj1
删除此对象事件筛选器对象obj。
当此对象被销毁时,此对象的所有事件过滤器将自动删除。
删除事件过滤器总是安全的,即使在事件过滤器激活期间(即从eventFilter()函数)。
void QObject::removeEventFilter(QObject *obj)
{
Q_D(QObject);
if (d->extraData) {
for (int i = 0; i < d->extraData->eventFilters.count(); ++i) {
if (d->extraData->eventFilters.at(i) == obj)
d->extraData->eventFilters[i] = nullptr;
}
}
}
childEvent有下面三种:
QEvent::ChildAdded, setParent或构造时传入parent时会触发parent的此事件
QEvent::ChildRemoved,setParent会从老父对象移除,老父对象触发此事件
QEvent::ChildPolished,当对象改变时触发此事件,
如QWidget的adjustSize(),setVisible(bool visible),showNormal,showMaximized,showFullScreen,showMinimized等
QObject默认空实现
void QObject::childEvent(QChildEvent * /* event */)
{
}
void myobject::childEvent(QChildEvent *event)
{
qDebug()<<"QChildEvent="<<event->type()<<objectName();
}
myobject *obj1= new myobject("obj1");
myobject *obj2= new myobject("obj2");
myobject *obj3= new myobject("obj3");
obj1->setObjectName("obj1");
obj1->setObjectName("obj2");
obj3->setObjectName("obj3");
obj3->setParent(obj1);//触发obj1的ChildAdded
obj3->setParent(obj2);//触发obj1的ChildRemoved和obj2的ChildAdded
输出:
QChildEvent= QEvent::ChildAdded "obj1"
QChildEvent= QEvent::ChildRemoved "obj1"
QChildEvent= QEvent::ChildAdded "obj2"
自定义事件的id范围:
QEvent::User = 1000, // 自定义事件的起始id
QEvent::MaxUser = 65535 // 自定义事件的最大id
一般都是继承后重写实现自己的功能
自定义事件3步骤:
1、注册事件类型调用int QEvent::registerEventType(int hint = -1 )
//一般我们不需要传hint。除非你要定义事件号值并根据值做一些判断,hint取值范围[1000,65535],
但是也有可能被别人注册过所以返回的不一定是传入的值,可以直接使用注册返回的值作为类型判断即可
2、继承QEvent实现自定义事件类 ,如果事件不带数据的话可以直接使用QEvent
3、实现customEvent事件
4、发送事件并自动调用customEvent函数
QObject默认空实现
void QObject::customEvent(QEvent * /* event */)
{
}
//1定义两个事件类型
QEvent::Type myQEventType1 = static_cast<QEvent::Type>(QEvent::registerEventType());
QEvent::Type myQEventType2 = static_cast<QEvent::Type>(QEvent::registerEventType(1234));
//2继承QEvent
class myQEvent:public QEvent
{
public:
myQEvent(Type type, const QString &data)
: QEvent(type), m_data(data)
{}
QString m_data;//自定义事件传输的数据
};
//3实现customEvent事件
void myobject::customEvent(QEvent *event)
{
qDebug()<<"customEvent="<<event->type()<<static_cast<myQEvent*>(event)->m_data;
}
myobject *obj1= new myobject("boj1");
myobject *obj3= new myobject("boj3");
//4发送事件并自动调用customEvent函数
QApplication::sendEvent(obj1,new myQEvent(myQEventType1,"eeeeeeee"));
QApplication::sendEvent(obj3,new myQEvent(myQEventType2,"wwwwwwwww"));
//QApplication::sendEvent(obj3,new QEvent(myQEventType2));
//如果不传递数据的话,直接new QEvent传入自定义事件类型即可
customEvent输出:
ccustomEvent= QEvent::MaxUser "eeeeeeee"
customEvent= QEvent::Type(1234) "wwwwwwwww"