以前经常使用qt creator界面管理直接跳转到槽函数没发现这个问题,今天手动写了个槽函数发现按键会触发两次。根据网上的说法是按键会自动连接一个槽函数,如果我们手动添加的槽函数命名规则符合槽函数的命名规则的话,此时就会出现触发两次的问题。

  带着这个疑问,我们去代码里找答案。首先是在界面自动生成的ui_mainwindow.h(由你按键所在的界面决定),我们找到了自动建立槽函数连接的代码

       retranslateUi(MainWindow);
QMetaObject::connectSlotsByName(MainWindow);

  继续跟踪发现这个系统函数connectSlotsByName是定义在qobject中,切换过去发现文件头有如下声明

    \section1 Auto-Connection

    Qt's meta-object system provides a mechanism to automatically connect
signals and slots between QObject subclasses and their children. As long
as objects are defined with suitable object names, and slots follow a
simple naming convention, this connection can be performed at run-time
by the QMetaObject::connectSlotsByName() function.

  大意就是我们之前说的如果槽函数的命名满足一定形式的简单规则,那么这个函数就会将信号和槽自动连接起来,跟踪源代码我们看下规则到底是怎样的

 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) {
const char *slot = mo->method(i).signature();
Q_ASSERT(slot);
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();
if (!len || qstrncmp(slot + 3, objName.data(), len) || slot[len+3] != '_')
continue;
int sigIndex = co->d_func()->signalIndex(slot + len + 4);
if (sigIndex < 0) { // search for compatible signals
const QMetaObject *smo = co->metaObject();
int slotlen = qstrlen(slot + len + 4) - 1;
for (int k = 0; k < co->metaObject()->methodCount(); ++k) {
QMetaMethod method = smo->method(k);
if (method.methodType() != QMetaMethod::Signal)
continue; if (!qstrncmp(method.signature(), slot + len + 4, slotlen)) {
int signalOffset, methodOffset;
computeOffsets(method.enclosingMetaObject(), &signalOffset, &methodOffset);
sigIndex = k + - methodOffset + signalOffset;
break;
}
}
}
if (sigIndex < 0)
continue;
if (QMetaObjectPrivate::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);
}
}
}
大概看了下(有兴趣的可自行研究),要满足如图上红色标志处的如下两个规则
1、首先是要以on_开头
2、其次,要以“_”+行为结束,例如_clicked 了解这个后我们再回到之前的问题,假如一个按键QPushButton,如果我们定义一个槽函数on_QPushButton_clicked(void)的话,此时不需要额外进行connect()操作,程序编译时会自动将槽函数连接起来。
而这次如果我们额外进行connect操作的话,就会出现槽函数触发两次的情况了。
解决的办法很简单,手动连接时槽函数名字规避命名规则就行了,如上我们定义成QPushButton_clicked(void),或者在connect时使用qt::uniqueconnection进行强制制定。

  

QPushButton槽函数触发两次的问题的更多相关文章

  1. Qt发送一次信号触发两次槽函数的原因

    在手动为控件编写槽函数的时候,如果将槽函数名字按如下格式编辑,则不需要再次进行手动关联 void on_pushButton_1_clicked(); void on_radioButton_clic ...

  2. 想在子线程里面触发的信号的槽函数在子线程执行,信号槽连接必须使用DirectConnection 方式(即使跨线程,也可以强迫DirectConnection,而不能是AutoConnection)

    Qt多线程的实现 1.继承QThread,重新run 2.继承Object,调用moveToThread方法 两种方法各有利弊:主要参考:http://blog.51cto.com/9291927/1 ...

  3. 【QT】多个槽函数绑定同一个信号的触发顺序

    目录 一.Qt 3.0(包含3.0) - Qt 4.5(包含4.5)版本之前 二.Qt 4.6(包含4.6)版本之后 一.Qt 3.0(包含3.0) - Qt 4.5(包含4.5)版本之前 「多个槽函 ...

  4. QT信号和槽函数学习笔记

    //connect 函数有4个参数 分别是 发送者 信号.接受者 ,槽 //connect(sender,signal,receiver,slot) /* * 信号和槽 * 信号 就是一个普通的函数 ...

  5. QT槽函数获取信号发送对象

    Qt 在槽函数中获取信号发送对象 Qt中提供了一个函数 qobject_cast(QObject *object),可以通过这个函数判断信号发出对象 Qt 帮助文档的解释: Returns the g ...

  6. Boost 信号与槽,获取槽函数返回值,使用占位参数传递信号携带的参数

    test1: 展示了, 1 信号与槽的基本使用,    2 要获取槽函数的返回值时的注意事项 #if 1 /* 参考blog https://www.cnblogs.com/jiayayao/p/62 ...

  7. PyQt Designer中连接信号和槽时为什么只能连接控件自己的信号和槽函数?

    老猿在学习ListView组件时,想实现一个在ListView组件中选中一个选择项后触发消息给主窗口,通过主窗口显示当前选中的项的内容. 进入QtDesigner后,设计一个图形界面,其中窗口界面使用 ...

  8. PyQt Designer中带参数的信号为什么匹配不到带参数的槽函数?

    老猿在学习ListView组件时,想实现一个在ListView组件中选中一个选择项后触发消息给主窗口,通过主窗口显示当前选中的项的内容. 进入QtDesigner后,设计一个图形界面,其中窗口界面使用 ...

  9. Qt 信号和槽函数

    信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性.当某个信号被发射,就需要调用与之相绑定的槽函数.这与Windows下的消息机制类似,消息机制是基于回调函数.一个回调即是一个函数的 ...

随机推荐

  1. vSan中见证组件witness详解

    witness在vSan中作为见证组件其作用类似于WinServer中的仲裁磁盘,当Cluster中某一节点发生故障时,来判断该节点上的对象在哪一个新的节点上继续承载.此处需要强调的是,witness ...

  2. Windows 7 控制面板Update选项灰色解决办法

    具体解决方法是开始-运行-regedit,打开注册表编辑器,在注册表里找: HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows,展开Windo ...

  3. Excel英语成绩单

  4. [COGS 0107][NOIP 2003] 传染病控制

    107. [NOIP2003] 传染病控制 ★★★   输入文件:epidemic.in   输出文件:epidemic.out   简单对比时间限制:1 s   内存限制:128 MB [问题背景] ...

  5. linux性能系列--内存

    一.啥是内存呢? 回答:内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁.计算机中所有程序的运行都是在内存中进行的,因此内存的性能对计算机的影响非常大. 内存(Memory)也被称为内存储器, ...

  6. CCControlExtension/CCControl

    #ifndef __CCCONTROL_H__ #define __CCCONTROL_H__ #include "CCInvocation.h" #include "C ...

  7. 【bzoj3456】 城市规划

    题目 一句话题意,无向连通图计数 技不如人,甘拜下风 设\(f_i\)表示\(i\)个节点构成的无向连通图数量 之后...之后就不会了 于是抄题解 考虑容斥 \[f_i=t_i-\sum_{j=1}^ ...

  8. 基于HP DL388 Gen 9服务器基本配置(ESXI 6.5)

    最近一段时间由于做毕业设计的原因,一直处于忙碌状态,刚做完毕业设计,导师处于项目的原因,买了一台惠普服务器(人民币1.7万),服务器自带的内存仅有16 G,硬盘也就只有600G,而且磁盘还做了raid ...

  9. 【bbs】index、post

    列表 奇数行和偶数行设置不同的背景 http://blog.csdn.net/facecrazy/article/details/51252850 实现ul li中的内容上下左右居中,不用设置li宽度 ...

  10. ethereumjs/ethereumjs-blockchain-2-test

    https://github.com/ethereumjs/ethereumjs-blockchain/tree/master/test 'use strict' const test = requi ...