Qt 4自动实现signal和slot的连接

来源:互联网 发布:事件视界 知乎 编辑:程序博客网 时间:2024/05/16 10:57

查看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<QObject *>(o, QString());
    for (int i = 0; i < mo->methodCount(); ++i) {

/*

slot是方法的名字,在以下的内容中,会把它分成三部分(依次判断该方法是否满足这三部分的条件):

第一部分:on_

第二部分:子对象名

第三部分:信号名

*/
        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();

 

当切换这个菜单时,会自动执行上面的成员函数。

 

原创粉丝点击