QMetaObject::connectSlotsByName 分析

xiaoxiao2021-02-27  194

查看Qt4的一些示例项目的时候,使用设计器打开其UI文件,在文件中竟然找不到signal和slot的连接。但是最终的程序,slot却又能准确的响应信号。打开通过ui文件自动生成的c++文件,其中也找不到connect语句,到底是怎么一回事?      经过逐语句的分析。终于发现连接的原因就在于setUi函数的最后一句      QMetaObject::connectSlotsByName(MainWindow);       找到该静态函数      void QMetaObject::connectSlotsByName(QObject *o)   {    if (!o)    return;    const QMetaObject *mo = o->metaObject();    Q_ASSERT(mo);    const QObjectList list = qFindChildren(o, QString());    for (int i = 0; i < mo->methodCount(); ++i) {          const char *slot = mo->method(i).signature();    Q_ASSERT(slot);      //以下一行用来判断slot的前三位是否是on_,如果不是,就跳过这个方法。    if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')    continue;    bool foundIt = false;      //遍历子对象。    for(int j = 0; j < list.count(); ++j) {    const QObject *co = list.at(j);      //得到子对象名。    QByteArray objName = co->objectName().toAscii();    int len = objName.length();      //要求slot跳过前3位(on_)后,接下来的子字符串和子对象名相同,并且接着该子字符串又是一个_      //如果达不到这个要求,continue    if (!len || qstrncmp(slot + 3, objName.data(), len) || slot[len+3] != '_')    continue;    const QMetaObject *smo = co->metaObject();    int sigIndex = smo->indexOfMethod(slot + len + 4);    if (sigIndex < 0) { // search for compatible signals    int slotlen = qstrlen(slot + len + 4) - 1;      //搜索该子对象所能引发的信号    for (int k = 0; k < co->metaObject()->methodCount(); ++k) {   //方法类型如果符合要求       if (smo->method(k).methodType() != QMetaMethod::Signal)    continue;      //如果slot最后的子字符串和信号名相同       if (!qstrncmp(smo->method(k).signature(), slot + len + 4, slotlen)) {    sigIndex = k;    break;    }    }    }    if (sigIndex < 0)    continue;      //连接操作    if (QMetaObject::connect(co, sigIndex, o, i)) {    foundIt = true;    break;    }    }      //连接成功    if (foundIt) {    // we found our slot, now skip all overloads    while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)    ++i;    }      //连接失败      else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {    qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);    }    }   }      得出此结论:自动生成的文件中,该函数总会存在setUi函数的最后一句。      该函数的作用就是寻找setUi的唯一指针参数MainWindow所指向对象的成员函数,      该成员函数的名字如果满足以下条件,就做连接操作。      函数名规则:on_子对象名_信号名      函数签名(即返回值与参数要符合slot要求)      所以,我们可以这样做:在qt设计器中添加按纽或者菜单项或者按纽项后,不用在设计器中手动做连接操作。      我们只要在主窗口类中添加符合条件的成员函数即可。      函数名规则:on_子对象名_信号名      函数签名(即返回值与参数要符合slot要求)      例如:      在设计器中添加一个菜单项,其对应的action为actionNew      那么在主窗口类中添加以下的函数      public slots:       void on_actionNew_triggered();      当切换这个菜单时,会自动执行上面的成员函数。

转载请注明原文地址: https://www.6miu.com/read-12025.html

最新回复(0)