信号槽是 Qt 框架引以为豪的机制之一。

所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种触发是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。(这里提一句,Qt 的信号槽使用了额外的处理来实现,并不是 GoF 经典的观察者模式的实现方式。)

信号和槽是Qt特有的信息传输机制,是Qt设计程序的重要基础,它可以让互不干扰的对象建立一种联系。

槽的本质是类的成员函数,其参数可以是任意类型的。和普通C++成员函数几乎没有区别,它可以是虚函数;也可以被重载;可以是公有的、保护的、私有的、也可以被其他C++成员函数调用。唯一区别的是:槽可以与信号连接在一起,每当和槽连接的信号被发射的时候,就会调用这个槽。

信号与槽的连接:

 C++ Code 
1
2
3
4
5
6
7
8
 
static QMetaObject::Connection
connect(
    const QObject *sender,                          // 参数一:发送者
    const QMetaMethod &signal,                      // 参数二:信号
    const QObject *receiver,                        // 参数三:接收者
    const QMetaMethod &method,                      // 参数四:槽
    Qt::ConnectionType type = Qt::AutoConnection);  // 参数五:连接类型

注意:信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。如果不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少),但是不能说信号根本没有这个数据,你就要在槽函数中使用(就是槽函数的参数比信号的多,这是不允许的)。

信号槽的书写方式:

  • Qt4的书写方式

QPushButton* button = new QPushButton("Quit");

connect(button, SIGNAL(clicked()), &a, SLOT(quit()));

这种写法没有编译错误,而是在运行时给出错误,无疑会增加程序的不稳定性。

只有在 Debug 模式下运行时才会提示槽函数不存在,Release 模式下运行时不会给予任何错误提示。

  • Qt5的书写方式

QPushButton button("Quit");

QObject::connect(&button, &QPushButton::clicked, &app,&QApplication::quit);

  • C++11新方式: Lambda表达式,需要再Pro项目文件中加入 CONFIG += C++ 11

QPushButton* button = new QPushButton("Quit");

connect(button, SIGNAL(clicked()),[=](QString str){

                 qDebug() << str;});

关于Lambda表达式的知识

简单地说,Lambda表达式就是匿名函数。

以一对方括号[]开始,称为Lambda表达式的引入符。

引入符后面可以添加Lambda表达式的返回值类型。

接着是参数列表,最后是Lambda表达式的函数体。

引入符描述函数体如何“获得”外部变量!

所谓“外部变量”指的是函数体以外的变量,这些变量需要在引入符可见的作用域中有定义。

Lambda表达式构成图解:

  • Capture clause: 捕获子句
  • Parameter list: 参数列表 可选
  • Mutable specification 可选
  • Exception specification 可选
  • Return type: 返回类型 可选
  • Lambda Body

需要注意的一点:在进行信号槽绑定时,如果有重载,需要对成员函数进行类型转换,可以使用 C++ 的 static_cast 类型转换(编译时进行语法检查),也可以使用传统的 C 语言的强制类型转换(编译时不进行语法检查,运行时才检查),或者 C++11 的 QOverload::of,C++14 的 qOverload:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
QComboBox *comboBox = new QComboBox();
comboBox->addItem("Michael");
comboBox->addItem("Kobe");
comboBox->addItem("James");
comboBox->show();

// [1]
QObject::connect(comboBox,
                 static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
                 [](int index)
{
    qDebug() << index;
});

// [2]
QObject::connect(comboBox,
                 static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::activated),
                 [](const QString &text)
{
    qDebug() << text;
});

// [3]: QOverload<> 里面是参数列表,of() 里面是成员函数地址
QObject::connect(comboBox,
                 QOverload<const QString &>::of(&QComboBox::activated),
                 [](const QString &text)
{
    qDebug() << text;
});

QT信号槽连接语法总结的更多相关文章

  1. QT信号槽连接

    一:信号槽是什么? Qt的信号和槽机制是Qt的一大特点,实际上这是和MFC中的消息映射机制相似的东西,要完成的事情也差不多,就是发送一个消息然后让其它窗口响应,当然,这里的消息是广义的说法,简单点说就 ...

  2. Qt——信号槽连接:基于字符串与基于函数的连接之间的不同

    从Qt5.0开始,Qt提供了两种不同的方式进行信号槽的连接:基于 字符串 的连接语法.基于 函数 的连接语法.这两种语法各有利弊,下面对它们的不同点进行总结. 以下几部分详细解释了它们之间的不同,并说 ...

  3. Qt信号槽连接在有默认形参下的情况思考

    写下这个给自己备忘,比如函数 ) 你在调用端如论是test(3)或者test(),都可以正确调用到这个函数. 但是,如果放到Qt中的信号槽的话,这个还是值得讲一讲的,不然的话,可能会引起相应的误会. ...

  4. Qt 学习之路:深入 Qt5 信号槽新语法

    在前面的章节(信号槽和自定义信号槽)中,我们详细介绍了有关 Qt 5 的信号槽新语法.由于这次改动很大,许多以前看起来不是问题的问题接踵而来,因此,我们用单独的一章重新介绍一些 Qt 5 的信号槽新语 ...

  5. Qt 学习之路 2(16):深入 Qt5 信号槽新语法

    Qt 学习之路 2(16):深入 Qt5 信号槽新语法  豆子  2012年9月19日  Qt 学习之路 2  53条评论 在前面的章节(信号槽和自定义信号槽)中,我们详细介绍了有关 Qt 5 的信号 ...

  6. Qt信号槽的一些事(第一次知道信号还有返回值,以及Qt::UniqueConnection)

    注:此文是站在Qt5的角度说的,对于Qt4部分是不适用的. 1.先说Qt信号槽的几种连接方式和执行方式. 1)Qt信号槽给出了五种连接方式: Qt::AutoConnection 0 自动连接:默认的 ...

  7. Qt信号槽的一些事 Qt::带返回值的信号发射方式

    一般来说,我们发出信号使用emit这个关键字来操作,但是会发现,emit并不算一个调用,所以它没有返回值.那么如果我们发出这个信号想获取一个返回值怎么办呢? 两个办法:1.通过出参形式返回,引用或者指 ...

  8. Qt信号槽的一些事

    注:此文是站在Qt5的角度说的,对于Qt4部分是不适用的. 1.先说Qt信号槽的几种连接方式和执行方式. 1)Qt信号槽给出了五种连接方式: Qt::AutoConnection 0 自动连接:默认的 ...

  9. QT 信号槽connect中解决自定义数据类型或数组作为函数参数的问题——QT qRegisterMetaType 注册MetaType——关键:注册自定义数据类型或QMap等容器类

    一般情况下信号槽直接连接方式不会出现问题,但是如果信号与槽在不同线程或Qt::QueuedConnection方式连接,可能会在连接期间报以下类似问题,如: QObject::connect: Can ...

随机推荐

  1. C#_.NetFramework_Web项目_EXCEL数据导入

    [推荐阅读我的最新的Core版文章,是最全的介绍:C#_.NetCore_Web项目_EXCEL数据导出] 需要引用NPOI的Nuget包:NPOI-v2.4.1 B-1:EXCEL数据导入--C#获 ...

  2. C# detect latest .net framework installed on PC

    static void GetNetVersionDemo() { using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.L ...

  3. goweb-mysql连接

    操作 数据库 Go 语言中的 database/sql 包定义了对数据库的一系列操作.database/sql/driver 包定义了应被数据库驱动实现的接口,这些接口会被 sql 包使用.但是 Go ...

  4. Bootstrap 基于Bootstrap和JQuery实现动态打开和关闭tab页

    基于Bootstrap和JQuery实现动态打开和关闭tab页   by:授客 QQ:1033553122 1.   测试环境 JQuery-3.2.1.min.j Bootstrap-3.3.7-d ...

  5. linux脚本判断当前的linux版本是6还是7

    #!/bin/sh version="release 7." release=$(cat /etc/redhat-release) echo $release result=$(e ...

  6. 查询物料单位PAC成本

    select cpp.period_name 期间名称, ccga.organization_id 组织ID, ood.ORGANIZATION_CODE 组织代码, OOD.ORGANIZATION ...

  7. linux学习(四)复制(cp)移动(mv)删除(rm)查找(find)文件、文件夹操作、软硬链接的区别

    目录 复制文件 mv命令 rm命令 touch 命令 file命令 find命令 grep命令 mkdir命令 rmdir命令 @(复制移动删除查找文件.软硬链接的区别) 复制文件 cp命令用于复制文 ...

  8. MyBatis之接口绑定方案及多参数传递

    1.说明   所谓的MyBatis接口绑定,指的是实现创建一个接口后,把mapper.xml 由mybatis 生成接口的实现类,通过调用接口对象就可以获取mapper.xml 中编写的sql.在SS ...

  9. Golang防止多个进程重复执行

    创建锁文件 lockFile := "./lock.pid" lock, err := os.Create(lockFile) if err != nil { log.Fatal( ...

  10. Less(4)

    1.先判断注入类型 (1)首先看到要求,要求传一个ID参数,并且要求是数字型的:?id=1 (2)再输入?id=1' 界面无变化 (3)再输入?id=1'' 界面还是无变化, (4)再输入?id=1 ...