QT信号槽详解
1 QT信号槽详解
1.1 信号和槽的定义
信号是触发信号,例如按钮的点击触发一个clicked信号,槽是用来接收信号,并处理信号,相当于信号响应函数。一个信号可以关联多个槽函数,信号也可以连接信号。
要使用信号槽,类必须继承与QObject类或者其子类,否则无法识别槽函数错误。在类的定义开头需要添加宏定义Q_OBJECT。如下
class AlarmCenter : public QWidget
{
Q_OBJECT
//用关键字signals定义信号,关键字slots定义槽函数。如下所示:
public slots:
void SlotHideNoPlatPalyerTip(int tip);
signals:
void signalHideNoPlatPalyerTip (int tip);
}
信号和槽函数之间采用connect函数进行连接,采用disconnect函数取消连接。在需要触发信号的地方,采用关键字emit signalHideNoPlatPalyerTip (3);触发信号,调用槽函数,传入参数。
1.2 信号槽的连接方式
1.2.1 按照名称自动关联
自动关联需要响应函数的名称按照格式 on_按钮的名称_信号名称()来书写,并将该函数声明为槽slots。点击按钮的时候就会自动关联该信号到该响应函数。
头文件中:
public slots:
void on_BtnStart_clicked();
源文件中:
void AlarmCenter::on_BtnStart_clicked()
{
int i = 0;
}
1.2.2 Connect连接信号与槽函数
(1)无参数信号槽函数连接
&获取指针需要指定类名称,用宏定义SIGNAL和SLOT可以直接指定函数名称。
QObject::connect(ui.fliterBtn, &QToolButton::clicked, this, &AlarmCenter::DisplayFliterWidget);
connect(ui.fliterBtn, SIGNAL(clicked()), this, SLOT(DisplayFliterWidget ()));
(2)有参数信号槽函数连接
signals:
void valueChanged(int value);
slots:
void AlarmCenter::AlarmListVScrool(int position);
&方式无需添加参数,SIGNAL和SLOT方式则要添加参数,注意使用&方式时,如果槽函数是重载函数,则编译出错,因为没有参数,无法判断是连接哪个槽函数,所以建议采用,SIGNAL和SLOT方式带上参数。多个参数用逗号隔开,只添加形参类型,不加形参实体。
QObject::connect(ui.verticalScrollBarAlarm, &QScrollBar::valueChanged, this, &AlarmCenter::AlarmListVScrool);
QObject::connect(ui.verticalScrollBarAlarm, SIGNAL(valueChanged(int)), this, SLOT(AlarmListVScrool(int)));
对于有重载函数的槽函数,需要用到有参数的连接方式,否则无法判断是哪个槽函数。
(3)自定义结构体参数的信号槽连接
对于自定义的结构体参数,信号槽无法识别参数,导致信号槽连接不起作用。所以需要注册结构体参数。在结构体中声明结束的地方加上结构体注册。
struct DealDetailInfo
{
};
Q_DECLARE_METATYPE(DealDetailInfo);
信号定义
signals:
void signalOnePointUpdateData(QVariant VarDetailInfo);
槽函数定义
void SlotOnePointUpdateData(QVariant VarDealInfo);
信号槽连接
QObject::connect(&m_DealDetail, SIGNAL(signalOnePointUpdateData(QVariant)), this, SLOT(SlotOnePointUpdateData(QVariant)), Qt::QueuedConnection);
发送信号的地方用变量QVariant包装结构体参数
QVariant DataVar;
DataVar.setValue(DetailInfo);
emit signalOnePointUpdateData(DataVar);
接收信号的地方从包装中取出结构体参数
DealDetailInfo DealInfo;
DealInfo= VarDealInfo.value<DealDetailInfo>();
1.2.3 信号与信号连接
当存在复杂的包含关系时,A是B的成员对象,B是C的成员对象。在A中触发的信号需要C中的槽函数响应,则需要连接A中的信号触发B中的信号,B中的信号触发C中的槽函数。例子如下:
Class A
{
signals:
signalChangeColor(int i);
}
Class B
{
signals:
signalChangeColor(int i);
privite:
A a;
}
QObject::connect(&a,SIGNAL(signalChangeColor(int)), this, SIGNAL(signalChangeColor(int)));
Class C
{
public lots:
SlotChangeColor(int i)
privite:
B b;
}
QObject::connect(&b,SIGNAL(signalChangeColor(int)),this, SLOT(SlotChangeColor(int i)));
1.2.4 信号和lambda表达式连接
当槽函数比较简单,没有必要创建一个槽函数去连接,可以直接用一段简短的代码作为信号接收处理。日下所示。
QObject::connect(ui.closeDisPlayImageWndBtn, &QToolButton::clicked, this, [=]()
{
m_imageWidth = 0;
m_imageHeight = 0;
m_iPercent = 100;
m_izoomLevel = 0;
close();
});
或者控件是new出来的,需要关联控件信号到函数
QCheckBox *CheckBox = new QCheckBox(ui.tableWidget);
QSize size(39, 35);
CheckBox->setFixedSize(size);
CheckBox->setCheckState(Qt::Unchecked);
QObject::connect(CheckBox, &QCheckBox::clicked,this, [=]()
{
AlarmTableItemChoosed(step, 0);//成员函数
});
1.2.5 QT Designer界面上连接信号槽
进入QT Designer 界面,点击信号槽编辑按钮,进入信号槽编辑界面,拖动按钮,对按钮的信号槽进行编辑,可以选用已有的槽,或者点击编辑按钮,新增自定义槽。关联之后,在ui_*.h(*表示对话框类名)中会自动添加一行,QObject::connect(BtnStart, SIGNAL(clicked()), AlarmCenterClass, SLOT(sbclslot()));然后在dialog类的文件中实现该槽。
1.3 信号槽的连接响应类型
连接信号与槽的connect()函数原型如下:
bool QObject::connect ( const QObject * sender, const QMetaMethod & signal, const QObject * receiver, const QMetaMethod & method, Qt::ConnectionType type = Qt::AutoConnection );
最后一个参数Qt::ConnectionType是连接类型,不同的连接类型,槽函数的响应策略如下:
Constant |
Value |
Description |
Qt::AutoConnection |
0 |
自动识别。当信号发送者和接收者处于同一线程内时,这个类型等同于DirectConnection,反之等同于QueuedConnection,这个类型也是connect函数的默认连接类型 |
Qt::DirectConnection |
1 |
同步执行。信号一旦发射,与之关联的槽函数立即执行,执行返回后才能执行emit之后的代码,相当于函数调用。 |
Qt::QueuedConnection |
2 |
异步执行。当信号产生,信号会暂时被缓冲到一个消息队列中,不用等待槽函数返回,就会执行后面的代码。等待接收者的事件循环处理去队列中获取消息,然后执行和信号关联的槽函数,这种方式既可以在同一线程内传递消息也可以跨线程操作 |
Qt::BlockingQueuedConnection |
3 |
阻塞执行。这种类型类似于QueuedConnection,但是它只能应用于跨线程操作即发送者和接收者处于不同的线程中的情况,并且信号发送者线程会阻塞等待接收者的槽函数执行结束。如果是同一个线程调用,会造成死锁现象。 |
Qt:: Unique Connection |
0x80 |
作用相当于Qt::AutoConnection。只是防止重复连接。如果当前信号和槽已经连接过了,就不再连接了。 |
1.4 一个信号多个槽函数的调用顺序
存在一个信号连接多个槽函数的情况,槽函数的调用顺序与连接的先后一致,但这只适用于同步调用,异步调用是加入到信号队列中,无法判断调用先后顺序。
1.5 带返回值的信号
大都说Qt信号槽不能使用返回值。Qt5中,信号槽是有返回值的。只是Qt的一个信号可以连接多个槽,还有同步调用和异步调用的问题,没发支持的很好,所以,返回值虽有,但只是鸡肋。同步调用才有返回值,异步调用的返回值永远为返回值类型默认构造函数出来的。连接的多个槽都返回值,那么结果是最后调用(连接)的那个。也就是说对于QueuedConnection连接的信号槽,永远只是返回返回类型的默认构造函数的。对于AutoConnection连接的,如果发出信号的线程和槽函数线程不同亦然。所以只有同步调用或者阻塞调用,才会成功返回值。
bool bReturn;
QMetaObject::invokeMethod(&object, "signalname", Qt::DirectConnection/* Qt::BlockingQueuedConnection */, Q_RETURN_ARG(bool, bReturn), Q_ARG(int, i));
QT信号槽详解的更多相关文章
- QT源码之Qt信号槽机制与事件机制的联系
QT源码之Qt信号槽机制与事件机制的联系是本文要介绍的内容,通过解决一个问题,从中分析出的理论,先来看内容. 本文就是来解决一个问题,就是当signal和slot的连接为Qt::QueuedConne ...
- Qt信号槽的一些事(第一次知道信号还有返回值,以及Qt::UniqueConnection)
注:此文是站在Qt5的角度说的,对于Qt4部分是不适用的. 1.先说Qt信号槽的几种连接方式和执行方式. 1)Qt信号槽给出了五种连接方式: Qt::AutoConnection 0 自动连接:默认的 ...
- QT 信号槽connect中解决自定义数据类型或数组作为函数参数的问题——QT qRegisterMetaType 注册MetaType——关键:注册自定义数据类型或QMap等容器类
一般情况下信号槽直接连接方式不会出现问题,但是如果信号与槽在不同线程或Qt::QueuedConnection方式连接,可能会在连接期间报以下类似问题,如: QObject::connect: Can ...
- Qt信号槽的一些事 Qt::带返回值的信号发射方式
一般来说,我们发出信号使用emit这个关键字来操作,但是会发现,emit并不算一个调用,所以它没有返回值.那么如果我们发出这个信号想获取一个返回值怎么办呢? 两个办法:1.通过出参形式返回,引用或者指 ...
- Qt信号槽的一些事
注:此文是站在Qt5的角度说的,对于Qt4部分是不适用的. 1.先说Qt信号槽的几种连接方式和执行方式. 1)Qt信号槽给出了五种连接方式: Qt::AutoConnection 0 自动连接:默认的 ...
- Qt信号槽-原理分析
目录 一.问题 二.Moc 1.变量 2.Q_OBJECT展开后的函数声明 3.自定义信号 三.connect 四.信号触发 1.直连 2.队列连接 五.总结 六.推荐阅读 一.问题 学习Qt有一段时 ...
- Qt信号槽源码剖析(一)
大家好,我是IT文艺男,来自一线大厂的一线程序员 大家在使用Qt开发程序时,都知道怎么使用Qt的信号槽,但是Qt信号槽是怎么工作的? 大部分人仍然不知道:也就是说大家只知道怎么使用,却不知道基于什么原 ...
- Qt信号槽源码剖析(二)
大家好,我是IT文艺男,来自一线大厂的一线程序员 上节视频给大家讲解了Qt信号槽的基本概念.元对象编译器.示例代码以及Qt宏:今天接着深入分析,进入Qt信号槽源码剖析系列的第二节视频. Qt信号槽的宏 ...
- (文字版)Qt信号槽源码剖析(三)
大家好,我是IT文艺男,来自一线大厂的一线程序员 上节视频给大家讲解了Qt信号槽的Qt宏展开推导:今天接着深入分析,进入Qt信号槽源码剖析系列的第三节视频. Qt信号槽宏推导归纳 #define si ...
随机推荐
- P2473 [SCOI2008]奖励关(期望)
P2473 [SCOI2008]奖励关 $n<=15$,显然的状压 设$f[i][w]$表示前$i$轮,状态$w$的最大期望 蓝后我们发现一个问题:$f[i][w]$可能是非法的 于是我们从$f ...
- Pycharm创建Django项目并访问Django
Pycharm创建Django项目并访问Django 一.Django插件 如果没有Django插件,需要先安装Django插件. 1,首先点击Default Settings,打开设置页面: 2,打 ...
- vs变量监视提示-VAR-CREATE: UNABLE TO CREATE VARIABLE OBJECT解决方法
昨天有个linux应用在使用vs 远程debug的时候,debug可以正常进行,但是监视变量的时候提示-VAR-CREATE: UNABLE TO CREATE VARIABLE OBJECT,经测试 ...
- devexpress 之 ChartControl
\}5#~mV#cr(/k1yIZ7.Lg
- 爬虫的基本操作 requests / BeautifulSoup 的使用
爬虫的基本操作 爬虫基础知识 什么是爬虫? 在最开始,还没有诞生Google和百度等一系列搜索引擎的公司的时候,人们进入一些公司的网站只能通过在浏览器地址栏输入网址的方式访问,如同在很早之前前手机不流 ...
- 如何将QT的pro图标修改的更显著一些
如何将QT的pro图标修改的更显著一些 QT的项目打开文件是pro,默认是这样的 这个白色的背景在很多文件中很不好找 所以使用工具进行相关修改. 寻找到.pro 双击修改ico 默认的这个就非常不错. ...
- NOI 2007 货币兑换Cash (bzoj 1492) - 斜率优化 - 动态规划 - CDQ分治
Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个 ...
- 【python007 -分支和循环】
一.打飞机游戏的实现逻辑: 加载背景音乐 播放背景音乐(设置单曲循环) 我方飞机诞生 interval = 0 #小飞机没诞生一个就会移动一个位置,那这样的话,会在屏幕出现密密麻麻的飞机,所以要加一 ...
- topcoder srm 662 div1
problem1 link 首先枚举差值$d$,判断是否存在一个序列任意连续两个之间的差值小于$d$. 首先将数字排序,然后从小到大依次放置每一个数字.每个当前的数字有两个位置可以放,当前序列的前面或 ...
- Linux lvm 分区知识笔记
盘面上可以细分出扇区(Sector)与柱面(Cylinder)两种单位,其中扇区每个为512bytes那么大. 通常所说的"硬盘分区"就是指修改磁盘分区表,它定义了"第n ...