这一篇学习QT中最重要的也是最有特色的信号槽机制。

(因为我学习过MFC,所以我觉得QT的信号槽机制和MFC中的消息响应机制是一一对应的。不过是MFC用的是宏来实现,而QT用的是消息和槽。相对来说QT可能会更灵活一点,但是也更容易出错

QT学习(二)

首先应该明白为什么要去用信号和槽,它是为了实现什么而存在的。

因为QT是GUI编程,GUI编程最关注的就是用户和应用程序的交互(通过将某种用户事件
(比如按下鼠标)与程序事件(比如退出程序)联系起来,使用户能够在图形界面中只使用鼠标来控制程序。)

其他的程序使用回调函数来处理这类问题的(其他不是所有)

(所谓的回调函数是指:按照一定的形式由开发人员定义并编写实现内
容。使用回调函数,实际上就是在调用某个函数(通常是API函数)时,将自
己的一个函数(也就是回调函数)的地址作为参数传递给那个函数。而那个
函数在需要的时候,也就是某种事情发生的时候,利用传递的函数地址调
用回调函数,这时开发人员可以利用这个机会在回调函数中处理消息或完
成一定的操作。然而会点函数十分的复杂不容易理解,所以就有了信号和槽)

信号和槽是为了实现对象与对象之间(跨越类的!!!!)通信而存在的,然而面向对象程序中就是将应用程序对象化,所以这种机制就能够实现用户事件和程序事件的交互。

Qt的窗口部件有很多预定义的槽,当一个特定事件发生的时候,一个信号被发射,对信号感兴趣的槽就会调用对应的响应函数。

在QObject类或者其一个子类(比如:QWidget类)继承的所有类中,都存在了信号和槽。当对象改变其状态的时候,信号被发送,对象不关心有没有其他对象接收到这个信号。槽是类的正常成员函数,可以将信号和槽通过connect()函数任意连接。当一个信号被发射,它所连接的槽会被立即执行,如同一个普通函数调用一样。

当信号被发出时,会调用与之相连接的槽。槽是普通的C++函数,可以用普通的方式来调用。它唯一特殊的地方在于可以与信号相连接。槽的参数不能有默认值。同样,信号的参数也不能有默认值。在槽的参数中尽量不使用自定义的数据类型,因为这样将会使通用性降低。

public slot: 任何信号都可以与之相连接。这在窗口部件编程中非常有用,用于创建一些对彼此一无所知的对象,只有                   通过信号和槽来交换信息。public slot就像是标准的铁路一样。
protected slot: 只有该类及其子类所派生的对象的信号才可以与之相接。这类槽的目的通常是为了类的完善,而不是类与外界的接口。
private slot: 只有该类自己的信号才可以与之相连接。

信号和槽是相当高效的。当然,它们与“实时”的回调函数相比,在增加了灵活性的同时也损失了一些速度,正所谓有利必有弊,但是这种速度的损失相当微不足道。因此,信号/槽机制具有的简便性和灵活性的特性,使用信号和槽是用户交互的必然选择
信号
当某个信号对其客户或所有者发生的内部状态发生改变,信号被一个对象发射。只有定义过这个信号的类及其派生类能够发射这个信号。当一个信号被发射时,与其相关联的槽将被立刻执行,就象一个正常的函数调用一样。信号-槽机制完全独立于任何GUI事件循环。只有当所有的槽返回以后发射函数(emit)才返回。如果存在多个槽与某个信号相联,那么,当这个信号被发射时,这些槽将会一个接一个地执行,但是它们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪个后执行。

需要注意的事项:

1 多重继承把QObject的子类作为第一个父类
class SomeClass : public QObject, public OtherClass
{
……
}
2 函数指针不能作为信号和槽的参数,在你考虑使用函数指针作为信号/槽的参数的时候,继承是一个不错的
替代方法
3 不能把友元声明friend放在信号或者槽的声明部分
4 把继承的成员函数升级为公有状态,这个C++特征对信号和槽并不适

5 因为元对象编辑器不能展开#define,所以,在信号和槽中类型宏作为
一个参数不能工作
6 构造函数不能用于信号部分和槽部分
7 属性的声明应该放在含有相应的读写函数的公有部分之前

槽和信号的具体使用方法:

在类定义的第一行加入Q_OBJECT宏。类中的其他项都需要一个分号
终止符,而Q_OBJECT宏却不需要,但如果喜欢,也可以加上分号(是因
为编译器在处理时根本不考虑分号)。我们可以按照以下方式定义一个类:
class SenderClass
{
Q_OBJECT
……
值得注意的是:在一个类中可以定义任意个槽和信号,但是Q_OBJECT只需要一次。向类定义中加入信号的原型。比如:如果信号将要发送一个字符串作为该信号的参数,那么原型大概以如下的方式去编写:
……
signals:
void newName(QString &name);

使用发送语句来调用所有监听这个信号的方法。这一步使用的语法和用来调用一个局部方法的语法是一样的,只不过这时用emit关键字开头:
QString name;
emit newName(name);

与信号一样,槽需要在类定义的上部加入Q_OBJECT宏:
class ReceiverClass
{
Q_OBJECT
……
向类定义中加入槽方法的原型。这个原型必须与它将要接收的信号一样(也就是说,具有同样的一套参数)。由于槽是方法,所以,在作为槽使用的同时,也可以被直接调用。槽的方法可以设置成为公有的属性。
public slots:
void nameChanged(QString &name);

注:编写代码创建将要发送信号的类的实例。只有这个实例的存在,才能把槽和信号联系在一起。把槽和信号连接起来。这个工作通常在构造函数中完成,但是如果这个对象构造得比较晚,那么连接工作也可以晚点做。调用connect()方法把你的槽加入到方法列表中,每当指定的信号发出的时候,这个方法就会被调用。

必须小心不要创建死循环。如果一个槽方法发送一个信号,此信号直接或者间接地执行了发送一个信号的方法,而这个信号又被最开始的槽所接收,那么信号将连续不断的调用槽,你编写的程序就会崩溃。比如:如果名为firstfun()的方法发送了一个A信号,A信号被second()槽所接收,而second()槽发送了信号B,最后,名为firstfun()的方法接收了信号B,这样就产生了一个死循环。这种循环将一直执行,直到该程序崩溃为止(或者用户进入长时间的等待)。还需要小心槽和信号方法在连接语句中的参数是否匹配。当程序运行的时候,直到试着去解决一个问题时,才可能得到出错的信息。为了避免这个问题的出现,必须确定每次增加内容的时候,都要进行测试,或者改变槽和信号部分。唯一的出错信息是当connect()方法找不到匹配对象的时候,输出一个写入控制台上的字符串。此后,程序就忽略了这个信号的存在。只有从命令行运行程序的时候,才能够看到控制台输出的信息。
connect(sender,SIGNAL(newName(QString &)),this,
SLOT(nameChanged(QString &)));
注:前两个参数指定信号的来源,后两个参数指定目标槽。宏SIGNAL()和SLOT()都需要完整的方法原型,原型必须遵循,用来调用一种方法的参数必须和该种方法可以使用的参数保持一致。无论任何使用emit发送信号,就好象是你编写的程序直接调用每一个槽方法一样。也就是说,直到槽方法返回,你编写的程序才能继续执行。因此,通常应当保持在槽方法内部的处理过程中尽可能的简单,这样才不会因此中止信号的发送。发送信号的可能是用户接口过程,操作过程表现得比较慢或者缓慢。

到这里QT最重要的特性已经OK,剩下的就是试练,敬仰,从下一章开始!!

QT学习(二)的更多相关文章

  1. qt学习(二) buttong layout spinbox slider 示例

    开启qt5 creator 新建项目 qt widgets 改写main.cpp #include "mainwindow.h" #include <QApplication ...

  2. QT学习二:工具栏

    QT  的工具栏提供 Dock 功能.文字/图标显示排列的功能. void MainWindow::createToolBar(void) { QToolBar *toolBar = new QToo ...

  3. QT学习第1天

    QT学习第一天  坚持住!! 一 Qt概述 1.Qt发展历史 (1)1991年诞生(Haavard Nord/Eirik Chambe-Eng), (2)1994年创立Troll Tech(奇趣科技) ...

  4. Qt 学习之路 2(56):使用模型操作数据库

    Qt 学习之路 2(56):使用模型操作数据库 (okgogo: skip) 豆子 2013年6月20日 Qt 学习之路 2 13条评论 前一章我们使用 SQL 语句完成了对数据库的常规操作,包括简单 ...

  5. Qt 学习之路 2(49):自定义只读模型

    Qt 学习之路 2(49):自定义只读模型 豆子 2013年5月5日 Qt 学习之路 2 18条评论 model/view 模型将数据与视图分割开来,也就是说,我们可以为不同的视图,QListView ...

  6. Qt 学习之路 2(45):模型

    Home / Qt 学习之路 2 / Qt 学习之路 2(45):模型 Qt 学习之路 2(45):模型  豆子  2013年2月26日  Qt 学习之路 2  23条评论 在前面两章的基础之上,我们 ...

  7. Qt 学习之路 2(44):QFileSystemModel

    Home / Qt 学习之路 2 / Qt 学习之路 2(44):QFileSystemModel Qt 学习之路 2(44):QFileSystemModel  豆子  2013年2月21日  Qt ...

  8. Qt 学习之路 2(29):绘制设备

    Qt 学习之路 2(29):绘制设备 豆子 2012年12月3日 Qt 学习之路 2 28条评论 绘图设备是继承QPainterDevice的类.QPaintDevice就是能够进行绘制的类,也就是说 ...

  9. Qt学习笔记-Widget布局管理

    Qt学习笔记4-Widget布局管理       以<C++ GUI Programming with Qt 4, Second Edition>为参考 实例:查找对话框 包含三个文件,f ...

随机推荐

  1. kali渗透测试阅读目录

    一.渗透测试介绍 渗透测试介绍及渗透环境配置 二.信息收集 kali 信息收集 三.漏洞扫描 kali 漏洞扫描 四.漏洞利用 kali msf漏洞利用

  2. UiPath剪贴板操作的介绍和使用

    一.剪切板操作的介绍 模拟用户使用剪切板操作的一种行为: 例如使用设置剪切板(SettoClipboard),从剪切板获取(GetfromClipboard)的操作 二.剪切板相关操作在UiPath中 ...

  3. flex大法:一网打尽所有常见布局

    flex全称Flexible Box模型,顾名思义就是灵活的盒子,不过一般都叫弹性盒子,所有PC端及手机端现代浏览器都支持,所以不用担心它的兼容性,有了这玩意,妈妈再也不用担心我们的布局. 先简单介绍 ...

  4. NC14326 Rails

    NC14326 Rails 题目 题目描述 There is a famous railway station in PopPush City. Country there is incredibly ...

  5. Burnside 引理与 Pólya 定理

    群 群的定义 在数学中,群是由一种集合以及一个二元运算所组成的,符合"群公理"的代数结构. 一个群是一个集合 \(G\) 加上对 \(G\) 的二元运算.二元运算用 \(\cdot ...

  6. Tomcat深入浅出——最终章(六)

    前言 利用了六天的时间,对Tomcat的内容进行了整理. 学习不易.整理也不易,自己坚持的更了下来,很不错. 希望每一位在努力前行的小伙伴,都要相信坚持就会有收获. 本次Tomcat就探寻到这里,明年 ...

  7. MySQL 啥时候用表锁,啥时候用行锁?

    大家好,我是树哥. MySQL Innodb 的锁可以说是执行引擎的并发基础了,有了锁才能保证数据的一致性.众所周知,我们都知道 Innodb 有全局锁.表级锁.行级锁三种,但你知道什么时候会用表锁, ...

  8. Centos7借助docker部署mysql,提供远程链接服务

    Centos7 借助docker部署mysql,并提供远程连接服务 安装docker 运行docker 注意安装docker和运行docker的步骤很简单,可以参考我学习docker的笔记 docke ...

  9. maven的常见问题

    idea2021.3报错-Maven-Terminated-with-exit-code-1

  10. 类型转换_float()函数

    float()函数不能将文字类的字符串类型转换成小数类型 同时将整数转换成浮点数类型的时候会在整数后买你加上.0 print(float(1))//output:1.0 print(float('1' ...