解读QT信号与槽机制里 QMetaObject::connectSlotsByName(QObject *o)的源码

Qt学习 第4节:QMetaObject::connectSlotsByName(this)信号槽自动连接 #include<QApplication> #include<QHBoxLayout> #include<QSlider> #include<QSpinBox> int main(int argc,char* argv[]) { QApplication app(argc,argv); QWidget* window = new QWidget; window->setWindowTitle("Enter Your. 阅读详情


介绍

connectSlotsByName 是一个QMetaObject类里的static函数,其定义如下:

static void connectSlotsByName(QObject *o);

其作用是如其名称一样,用来将QObject *o里的子孙QObject的某些信号按照其objectName连接到o的槽上。

起因

为啥会对这个函数产生一探究竟的想法呢?——

既然是根据objectName来连接信号和槽,那么就有了几个问题:

  1. 能不能对多个QObject设置同样的objectName呢?
  2. 如果能,那么connectSlotsByName会连接多少个QObject的信号到指定的槽上呢?

测试结果

有了疑问,第一个应该做的事情,当然是编写代码进行测试了。

在测试的主窗口类构造函数在“ui->setupUi(this); ”语句前编写如下代码:

     for ( int  i = 0 ;i < 9 ; ++ i)
    {
        QPushButton 
* btn = new  QPushButton( this );
        btn
-> setObjectName(“TestButton”);
        qDebug(btn
-> objectName().toStdString().c_str());
    }

    ui
-> setupUi( this );

QMetaObject::connectSlotsByName()这个函数会在ui->setupUi(this);里被调用执行。

然后在主窗口里增加下面的槽定义很代码:

 

     void  on_TestButton_clicked( bool  bVal);

    
void  MainWindow::on_TestButton_clicked( bool  bVal)
    {
        QObject 
* obj = sender();
        qDebug(
" TestButton is clicked by %s!%d/n " ,obj -> objectName().toStdString().c_str(),bVal);
    }

 

然后编译运行,结果出来了:

  1. 9个按钮的objectName()都返回"TestButton"
  2. 只有第一个按钮的clicked信号被连接到了on_TestButton_clicked槽上

第一个结论与我的猜想相符(后来看了QObject的源码,也是比较简单的),第二个结论与我的猜想有点不同,我本来猜想,应该是9个按钮的 clicked信号应该都可以连接到这个on_TestButton_clicked槽上的,但是却只有第一个连接上了,这是为什么呢?

让我们看看connectSlotsByName都干了些什么吧。

connectSlotsByName的源码解读

 

1 void QMetaObject::connectSlotsByName(QObject *o)
2 {
3     if (!o)
4         return;
5     const QMetaObject *mo = o->metaObject();
6     Q_ASSERT(mo);
7     const QObjectList list = qFindChildren<QObject *>(o, QString());
8     for (int i = 0; i < mo->methodCount(); ++i) {
9         const char *slot = mo->method(i).signature();
10         Q_ASSERT(slot);
11         if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
12             continue;
13         bool foundIt = false;
14         for(int j = 0; j < list.count(); ++j) {
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;
20             const QMetaObject *smo = co->metaObject();
21             int sigIndex = smo->indexOfMethod(slot + len + 4);
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
28                     if (!qstrncmp(smo->method(k).signature(), slot + len + 4, slotlen)) {
29                         sigIndex = k;
30                         break;
31                     }
32                 }
33             }
34             if (sigIndex < 0)
35                 continue;
36             if (QMetaObject::connect(co, sigIndex, o, i)) {
37                 foundIt = true;
38                 break;
39             }
40         }
41         if (foundIt) {
42             // we found our slot, now skip all overloads
43             while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)
44                   ++i;
45         } else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {
46             qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);
47         }
48     }
49 }

 

看connectSlotsByName的实现,可以注意到以下几个地方:

  1. 第7行,取得o的所有子对象,在测试的代码里,QPushButton都设置了this为父对象,所以它们显然会在这个列表里出现
  2. 第8行,是一个遍历o的方法的循环,o的信号和槽就在其中
  3. 第11行,对于方法名称不是"on_"开头的方法跳过不处理,这也说明,如果你在一个QObject子类里定义了"on_"开头的槽的话,一定会被connectSlotsByName函数进行搜索匹配的操作的
  4. 第14行开始到33行,开始遍历o的所有的子对象,试图匹配到与槽名称以及信号名称相应的子对象。首先取出其objectName()与槽名称里的第一个‘_’和第二个‘_’做名称匹配。其次取出子对象的所有信号,与第二个‘_’之后部分做匹配。
  5. 如果匹配成功,则会执行36行的连接代码。连接成功的话,就会在38行break中断循环。

看到第5点,已经很明了了,对于同名的控件,connectSlotsByName只会连接子对象链表里的第一个对象的信号到槽上。

总结和其他

 

做个小小的总结:

  1. 尽量不要让QObject出现相同objectName的情况
  2. 如果同名connectSlotsByName只能给其中一个建立缺省的信号和槽的连接
  3. 如果出现大量编码创建大量控件的情况,最好是自己去建立信号和槽的连接,而不是依赖connectSlotsByName来做到这个工作。connectSlotsByName更适合的任务是与desinger配合完成缺省的信号和槽的连接。

其他:

在测试过程中,曾经把ui->setupUi(this);放到了控件创建之前运行,结果运行时提示:

QMetaObject::connectSlotsByName: No matching signal for on_TestButton_clicked

从connectSlotsByName的代码可以看到这实际上执行的是第46行,如果在调试程序中遇到这样的信息,可以检查一下,是否是控件的objectName与你编写的槽里的objectName并不相符。

RML2016.10a (CNN、LSTM、CNN-LSTM、CNN-LSTM-Multi-head-attention, TensorFlow) RML2016.10a (CNN、LSTM、CNN-LSTM、CNN-LSTM-Multi-head-attention, TensorFlow) 包含所有数据和代码,支持一键运行(jupyter) 阅读详情

相关推荐

基于MediaPipe的智能俯卧撑计数与姿势矫正系统

在现代健身和体能训练中,俯卧撑是最基础也是最有效的自重训练动作之一。然而,许多人在进行俯卧撑训练时常常存在姿势不正确、计数不准确等问题。本文将介绍如何利用计算机视觉和姿态估计技术,开发一个智能的俯卧撑计数与姿势矫正系统。

qq_36224726的博客 916

QT 默认槽函数 connectSlotsByName浅析

在查看Qt一些项目的时候,代码中竟然找不到signal和slot的连接。但是最终的程序,slot却又能准确的响应信号。为什么? 经过一番认(上)真(网)学(百)习(度),在 ui->setupUi(this); 函数中最后有一句这样的代码: QMetaObject::connectSlotsByName(MainWindow); 再去看QT助手,其函数原型是这样的: [stati...

HelloKandy's Blog 1万+

常规波束形成——时域波束形成、频域波束形成

本文介绍了波束成形,包括时域波束成形和频域波束成形,并解释了在实现过程可能存在疑惑的相位补偿。

Candy_Editor的博客 3657

connectSlotsByName()函数的命名约定

这种命名约定的目的是简化信号和槽的连接过程,使代码更加易读和易于维护。通过一致地命名对象和槽函数,可以减少手动编写连接代码的工作量。函数会根据对象名和槽函数名之间的匹配关系自动连接信号和槽。它会在运行时查找对象中具有匹配名称的槽函数,并将其与相应的信号关联起来。事件或信号的名称应该采用驼峰命名法(首字母小写,后续单词首字母大写)。对象名:对象的名称应该以小写字母开头,后面可以跟随字母、数字或下划线。函数的命名约定是Qt框架中的一种约定,并非Python语言本身的约定。,那么相应的槽函数名称可以是。

扮作大侠的博客 803

Unity安卓打包实战:SDK与JDK配置全攻略

本文详细介绍了Unity安卓打包过程中SDK与JDK的配置方法,包括工具下载、安装步骤、环境变量设置及常见错误排查。通过实战指南帮助开发者快速完成Unity安卓打包环境搭建,提升开发效率。

weixin_30338481的博客 415

[V-10]ARMv8/v9-CPU Virtualization-CPU虚拟化架构简介(vCPU/vPE)

本文简要介绍了CPU虚拟化架构的基础知识。

基层架构师的分享 1267

QMetaObject::connectSlotsByName详解

一、介绍 如果使用ui acton编辑器,一般在代码中找不到生成的connnect函数,即关联信号与槽的函数,那么,信号与槽是怎么样关联起来的呢?答案就是靠这个函数connectSlotsByName来实现的。 二、使用方法 查看QT助手,其函数原型是这样的: [static] void QMetaObject::connectSlotsByName(QObject *object) 给出的说明:递归搜索给定对象的所有子对象,并将来自这些子对象的匹配信号连接到以下形式的对象插槽: void

sinat_31608641的博客 3499

YOLO26改进策略【Neck】| arXiv 2025 分层多头注意力HMHA 子空间拆分提多样 + 通道重排降冗余,强化目标检测精度

HMHA(Hierarchical Multi-Head Attention,分层多头注意力)旨在解决传统多头注意力(MHA)在图像恢复任务中的核心缺陷——特征冗余。传统MHA将通道均匀拆分给各个头,导致不同头学习的子空间信息相似,进而出现多头关注同一区域、忽略退化区域修复的问题,限制了模型的特征表达能力。HMHA通过“分层子空间拆分+通道重排序”策略,让每个头学习差异化、互补的上下文特征,从根源上缓解冗余,提升图像恢复任务中对复杂退化场景的特征捕捉能力。

Limiiiing的博客 209

为何有时候 找不到signal和slot的显示连接(connectSlotsByName),却能正常连接信号和槽呢?

在查看Qt一些项目的时候,代码中竟然找不到signal和slot的连接。假设我们的对象有一个类型为QPushButton的子对象,对象名为button1。2、如果同名,connectSlotsByName只会给其中一个建立缺省的信号槽的连接。在ui.widget.h文件中将会为每一个信号/槽建立connect;如果对象本身具有正确设置的对象名称,则其自身的信号也将连接到其各自的插槽。在widget.cpp文件中手动创建connect函数;在widget.h文件中手动创建槽函数;在界面组件上右键->转到槽;

zxf347085420的博客 654

零基础学simulink仿真建模--使用Simulink来构建一个混合动力无人机中燃料电池与锂电池协同控制的仿真模型

延长飞行时间:燃料电池的能量密度高于锂电池,适合长时间稳定供电。提高功率密度:锂电池能够快速响应瞬时高功率需求,比如起飞和加速阶段。优化能源管理:通过有效的能量管理系统,可以根据实际需求动态调整燃料电池和锂电池的工作状态,从而提高整体效率。通过上述步骤,我们简要介绍了如何基于Simulink实现混合动力无人机中燃料电池与锂电池协同控制的仿真模型。

amy_mhd的博客 189

YOLOv8改进策略【注意力机制篇】| CVPRW-2024 分层互补注意力混合层 H-RAMi 针对低质量图像的特征提取模块

许多证据表明层次化网络对图像恢复(IR)任务通常不太有效,因为IR的目标是逐个预测像素值(密集预测),而缩小特征图会丢失重要的像素级信息。然而,层次化结构有降低时间复杂度以及学习语义级和像素级特征表示的优点。为了弥补缺点并利用优点,设计了H - RAMi层。

Limiiiing的博客 377

Qt connectSlotsByName与信号槽

目录一 场景二 setupUi三 connectSlotsByName四 源码五 注意 一 场景 在 Qt connect与信号槽 一文中提到,信号槽主要通过 connect 进行连接,并且有好几种不同的写法。 新建一个Demo Widgets 程序。在 Qt 设计师界面中,拖入一个 QPushButton 控件,在其上右键 - 转到槽 - 选择信号 clicked(),会自动生成一个槽函数 on_pushButton_clicked()。发现点击按钮会触发该槽,但在代码中并没有找到 connect 的存

程序员Link 1706

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Qt:QMetaObject::connectSlotsByName实现信号槽自动关联

Qt:QMetaObject::connectSlotsByName实现信号槽自动关联

992

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

connectSlotByName()

缺省connect

孤鹜 451

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

QMetaObject.connectSlotsByName()的简单研究

是 Qt 框架中,无需手动调用connect()函数。

xulibo5828的博客 1079

PyQt5最全85 信号与槽之connectSlotsByName信号槽自动连接

PyQt5最全85 信号与槽之connectSlotsByName信号槽自动连接 from PyQt5.QtWidgets import * from PyQt5 import QtCore import sys class AutoSignalSlot(QWidget): """ 信号与槽自动连接 QMetaObject.connectSlotsByName 避免使用connect 规定格式:on_objectname_signalname eg: o

爱吃肉的牛牛的博客 1655

QT5 报错解决办法QMetaObject::connectSlotsByName: No matching signal for on_pushButton_clicked()

QT5报错: QMetaObject::connectSlotsByName: No matching signal for on_pushButton_clicked() 请检查你的信号对象是否已经被重新命名过,在UI界面右键“转到槽”的时候,按钮(或其他控件)被命名为“pushButton”,在编译的时候,该按钮(或其他控件)已经被重新命名为其他名称,QT无法找到信号与槽连接的目标。 ...

iXiaochu的博客 1万+

【信号与槽】connectSlotsByName()

#从ui文件转换成PY后自带的,connectSlotsByName作用是自动关联signal和slot QtCore.QMetaObject.connectSlotsByName(MainWindow) # 为按钮绑定单击信号 self.pushButton.clicked.connect(self.running) # 控制进度条的滚动效果 def running(self): if self.timer.isActive(): # 判断计时器是否开启 .

weixin_44628627的博客 771

Qt之connectSlotsByName分析

用于界面设置信号槽自动生成,要求槽函数定义形式为on_< objectName >_< signal >

多看多听多总结 461
上一篇: QObject ——QT所有类的基类
下一篇: S3C2410下嵌入式数据库SQLite的移植
control_tech
博客等级 码龄17年 53粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值