pyqt connectSlotsByName的使用,让你批量轻松的连接信号与槽

980 阅读1分钟

本文主要是本人学习中的一些知识记录,并非专业的文章。有误还请评论指出

connectSlotsByName 的使用

用qtdesigner中常见的比如QtCore.QMetaObject.connectSlotsByName(MainWindow)是自带的一种连接信号与槽的函数,他递归搜素MainWindow所有的子对象并将来自这些子对象的匹配信号连接到一下形式的对象槽def on_<object name>_<signal name>(<signal parameters>),对信号槽的匹配方式是先看前三位是不是on_,然后检测接着后面的字符串是否与子对象相同,如果相同再检测后面是不是_,附一段网上的源码

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

如果有一个QPushButton的子对象,对象名为button1,信号槽为def on_button1_clicked:,这时使用connectSlotsByName可以自动的将它们连接到一起,免去写connect的麻烦