QT学习(二)
这一篇学习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学习(二)的更多相关文章
- qt学习(二) buttong layout spinbox slider 示例
开启qt5 creator 新建项目 qt widgets 改写main.cpp #include "mainwindow.h" #include <QApplication ...
- QT学习二:工具栏
QT 的工具栏提供 Dock 功能.文字/图标显示排列的功能. void MainWindow::createToolBar(void) { QToolBar *toolBar = new QToo ...
- QT学习第1天
QT学习第一天 坚持住!! 一 Qt概述 1.Qt发展历史 (1)1991年诞生(Haavard Nord/Eirik Chambe-Eng), (2)1994年创立Troll Tech(奇趣科技) ...
- Qt 学习之路 2(56):使用模型操作数据库
Qt 学习之路 2(56):使用模型操作数据库 (okgogo: skip) 豆子 2013年6月20日 Qt 学习之路 2 13条评论 前一章我们使用 SQL 语句完成了对数据库的常规操作,包括简单 ...
- Qt 学习之路 2(49):自定义只读模型
Qt 学习之路 2(49):自定义只读模型 豆子 2013年5月5日 Qt 学习之路 2 18条评论 model/view 模型将数据与视图分割开来,也就是说,我们可以为不同的视图,QListView ...
- Qt 学习之路 2(45):模型
Home / Qt 学习之路 2 / Qt 学习之路 2(45):模型 Qt 学习之路 2(45):模型 豆子 2013年2月26日 Qt 学习之路 2 23条评论 在前面两章的基础之上,我们 ...
- Qt 学习之路 2(44):QFileSystemModel
Home / Qt 学习之路 2 / Qt 学习之路 2(44):QFileSystemModel Qt 学习之路 2(44):QFileSystemModel 豆子 2013年2月21日 Qt ...
- Qt 学习之路 2(29):绘制设备
Qt 学习之路 2(29):绘制设备 豆子 2012年12月3日 Qt 学习之路 2 28条评论 绘图设备是继承QPainterDevice的类.QPaintDevice就是能够进行绘制的类,也就是说 ...
- Qt学习笔记-Widget布局管理
Qt学习笔记4-Widget布局管理 以<C++ GUI Programming with Qt 4, Second Edition>为参考 实例:查找对话框 包含三个文件,f ...
随机推荐
- 记一次beego通过go get命令后找不到bee.exe的坑
学习goweb开发,gin是个轻量级的框架.如果想要一个类如aspnetmvc帮我们搭建好了的goweb框架,beego值得去学习.否则gin下面需要动手构建好多代码.新手还是先学现成的节约时间成本. ...
- js 表面学习 - 认识函数
JavaScript 函数语法 JavaScript 函数通过 function 关键词进行定义,其后是函数名和括号 (). 函数名可包含字母.数字.下划线和美元符号(规则与变量名相同). 圆括号可包 ...
- Servlet之Request和Response 解析
原理 tomcat服务器会根据请求url中的资源路径,创建对应的Servlet的对象 tomcat服务器.会创建request和response对象,request对象中封装请求消息数据. tomca ...
- 简单ELK配置实现生产级别的日志采集和查询实践
概述 生产问题 集群规模如何规划? 集群中节点角色如何规划? 集群之脑裂问题如何避免? 索引分片如何规划? 分片副本如何规划? 集群规划 准备条件 先估算当前系统的数据量和数据增长趋势情况. 现有服务 ...
- MySql字段增删改语句
新增表字段:alter table 表名 需要添加的字段信息; ALTER TABLE nation add seq VARCHAR(20) COMMENT '顺序' 字段名的修改:alter tab ...
- 鼠标右键打开powershell
不需要更改配置文件什么的. 在桌面空白处按住Shift键同时鼠标右击,看看是不是就有了呢.
- 没有Kubernetes怎么玩Dapr?
Dapr 被设计成一个面向开发者的企业级微服务编程平台,它独立于具体的技术平台,可以运行在"任何地方".Dapr本身并不提供"基础设施(infrastructure)&q ...
- Pytorch从0开始实现YOLO V3指南 part5——设计输入和输出的流程
本节翻译自:https://blog.paperspace.com/how-to-implement-a-yolo-v3-object-detector-from-scratch-in-pytorch ...
- StarGAN论文及代码理解
StarGAN的引入是为了解决多领域间的转换问题的,之前的CycleGAN等只能解决两个领域之间的转换,那么对于含有C个领域转换而言,需要学习C*(C-1)个模型,但StarGAN仅需要学习一个,而且 ...
- PTA(BasicLevel)-1013 数素数
一.问题描述 令 Pi 表示第 i 个素数.现任给两个正整数 M≤N≤104,请输出 PM 到 PN 的所有素数. 输出格式:输入在一行中给出 M 和 N,其间以空格分隔. 输 ...