QObject_event

QObject::event

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;
}

void QObject::installEventFilter(QObject *filterObj)

给对象安装一个事件过滤器即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);
}

bool eventFilter(QObject * watched, QEvent * event )

事件的处理流程就是先调用各种过滤函数,判断是否过滤,不过滤才会走到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

void QObject::removeEventFilter(QObject *obj)

删除此对象事件筛选器对象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

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"

customEvent

自定义事件的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"
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值