• 11184阅读
  • 8回复

[QT秘籍] QMetaObject::connectSlotsByName 分析,让自动连接为我所用! [复制链接]

上一主题 下一主题
离线kmax
 
只看楼主 倒序阅读 楼主  发表于: 2008-06-12
— 本帖被 XChinux 执行加亮操作(2008-06-13) —
下面是 QT 4.4.0 的QMetaObject::connectSlotsByName 源代码:

  1. void QMetaObject::connectSlotsByName(QObject *o)
  2. {
  3.     if (!o)
  4.         return;  //如果空,退出
  5.     const QMetaObject *mo = o->metaObject();
  6.     Q_ASSERT(mo); //如果不是一个meta Object
  7.     const QObjectList list = qFindChildren<QObject *>(o, QString()); //查找子对象,放入list
  8.     for (int i = 0; i < mo->methodCount(); ++i) {  //对于mo的所有方法
  9.         const char *slot = mo->method(i).signature(); //取出slot 的名字字符串
  10.         Q_ASSERT(slot);
  11.         if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
  12.             continue;  // 如果不是以on_开头,就下次继续
  13.         bool foundIt = false; //初始化foundIt 为假, 这是找到标志
  14.         for(int j = 0; j < list.count(); ++j) {  //对所有的子对象,去找它的signal
  15.             const QObject *co = list.at(j);
  16.             QByteArray objName = co->objectName().toAscii();
  17.             int len = objName.length();
  18.             if (!len || qstrncmp(slot + 3, objName.data(), len) || slot[len+3] != '_')
  19.                 continue; // 如果objName对不上on_后面的那个字符串的话,说明找错了子对象,继续下次
  20.             const QMetaObject *smo = co->metaObject();
  21.             int sigIndex = smo->indexOfMethod(slot + len + 4); //找到子对象的signal偏移
  22.             if (sigIndex < 0) { // search for compatible signals
  23.                 int slotlen = qstrlen(slot + len + 4) - 1;
  24.                 for (int k = 0; k < co->metaObject()->methodCount(); ++k) {
  25.                     if (smo->method(k).methodType() != QMetaMethod::Signal)
  26.                         continue;
  27.                     if (!qstrncmp(smo->method(k).signature(), slot + len + 4, slotlen)) {
  28.                         sigIndex = k;
  29.                         break;
  30.                     }
  31.                 }
  32.             }
  33.             if (sigIndex < 0)
  34.                 continue;
  35.             if (QMetaObject::connect(co, sigIndex, o, i)) {  // 如果连接成功了
  36.                 foundIt = true;
  37.                 break; // 一切搞定
  38.             }
  39.         }
  40.         if (foundIt) {
  41.             // we found our slot, now skip all overloads
  42.             while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)
  43.                   ++i;
  44.         } else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {
  45.             qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);
  46.         }
  47.     }
  48. }
[ 此贴被kmax在2008-06-13 13:24重新编辑 ]
QT 4.4.0  Win XP
离线kmax
只看该作者 1楼 发表于: 2008-06-12
经过我几个小时的艰苦探索,哈哈..终于搞定了,现在给大家分享一下吧...        

关键的关键是对象的 "父子关系" !! 必须让发出signal的对象是slot类的对象的儿子 !

这个很简单,只要先  m->setParent(this); // 其中,m是发出signal的对象,this是有slot的对象..

最后不要忘了, QMetaObject::connectSlotsByName(this); 哦,呵呵      

一切就这么简单,开始享受自动连接的快乐吧!!^_^  写个相应的on_xxxx_xxxx就可以了,再也不要一大堆的connect了...哈哈,,再见啦!

这个可是我自己分析QT源代码找到的方法哦..不要外传..官方文档里面都没有的哦!!啊哈哈

(不好意思,有点得意忘形了)
[ 此贴被kmax在2008-06-13 00:27重新编辑 ]
QT 4.4.0  Win XP
离线kmax
只看该作者 2楼 发表于: 2008-06-13
还有一点点小小的补充.. 当形成父子关系之后, 父对象析构的时候,会先析构子对象.. That means 你的槽没有了,发信号的对象也会随之消失!!

所以,不是什么地方都可以随便用的哦!!!
QT 4.4.0  Win XP
离线yuli
只看该作者 3楼 发表于: 2008-06-13
支持! 不过我刚刚学习QT 还很肤浅! 我要好学学! 呵呵    
离线kmax
只看该作者 4楼 发表于: 2008-06-13
我也是初学者啊,只是对C++比较熟,最近开始研究QT4的,可能大家都知道这个方法了吧? 呵呵.就我不知道
QT 4.4.0  Win XP
离线yleesun

只看该作者 5楼 发表于: 2008-06-13
楼主有QQ吗,我是刚学QT,现在要用QT4做项目。可以交流交流学习吗。
在下QQ:yleesun@163.com.欢迎QT爱好者加我,大家相互学习,共同进步。
离线linshihaoma

只看该作者 6楼 发表于: 2008-06-14
对楼主的探索精神深表敬意!
离线wbyqy

只看该作者 7楼 发表于: 2009-05-08
不知道楼主有没有遇到这样的问题,对自己在CPP中声明的对象并通过QMetaObject::connectSlotsByName( this );来让对象里面的信号与CPP文件中的一个void on_<widget name>_<signal name>(<signal parameters>);连接。功能成功实现了,但是后来发现了一个问题,假如我将QMetaObject::connectSlotsByName( this );重复多写了几次,void on_<widget name>_<signal name>(<signal parameters>);这个槽就多执行了几次,请问这是怎么回事?
离线leolio
只看该作者 8楼 发表于: 2011-04-14
楼主威武啊!!学习~~
快速回复
限100 字节
 
上一个 下一个