pinkyuanxue的个人主页

一块来学习!!!

http://www.qtcn.org/bbs/u/126669  [收藏] [复制]

pinkyuanxue

奋斗.....

  • 23

    关注

  • 26

    粉丝

  • 39

    访客

  • 等级:新手上路
  • 总积分:9
  • 女,1990-01-28

最后登录:2013-07-11

更多资料

日志

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

2012-08-03 11:42
转载自:http://blog.tianya.cn/blogger/post_show.asp?BlogID=2119015&PostID=17718002


查看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();
  
  当切换这个菜单时,会自动执行上面的成员函数。
分类:Qt 学习笔记|回复:0|浏览:1700|全站可见|转载
 

Powered by phpwind v8.7 Certificate Copyright Time now is:05-14 06:02
©2005-2016 QTCN开发网 版权所有 Gzip disabled