我的QT5学习之路(四)——信号槽
一、前言
前面说了Qt最基本的实例创建、控件以及工具集的介绍,相当于对于Qt有了一个初次的认识,这次我们开始认识Qt信号通信的重点之一——信号槽。
二、信号槽
信号槽是 Qt 框架引以为豪的机制之一。熟练使用和理解信号槽,能够设计出解耦的非常漂亮的程序,有利于增强我们的技术设计能力。
所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,用自己的一个函数(成为槽(slot))来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。(这里提一句,Qt 的信号槽使用了额外的处理来实现,并不是 GoF 经典的观察者模式的实现方式。)
#include "slottest.h"
#include <QtWidgets/QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication a(argc, argv); QPushButton button("Quit");
QObject::connect(&button,&QPushButton::clicked,&QApplication::quit);
button.show();
//slottest w;
//w.show();
return a.exec();
}
我们开始一步一步的分析这短短的几行代码。第6行声明一个QApplication类的对象,用于程序的启动和调用;第8行声明了一个按钮控件QPushButton类的对象,用于产生一个按钮,并传递一个字符串“Quit”命名控件显示的名称;第9行用到了QObject中的connect函数,我们先来看这个函数的定义。
/*Creates a connection of the given type from the signal in the sender object to the method in the receiver object. Returns a handle to the connection that can be used to disconnect it later. You must use the SIGNAL() and SLOT() macros when specifying the signal and the method*/
QMetaObject::Connection connect(const QObject *, const char *,
const QObject *, const char *,
Qt::ConnectionType); QMetaObject::Connection connect(const QObject *, const QMetaMethod &,
const QObject *, const QMetaMethod &,
Qt::ConnectionType); QMetaObject::Connection connect(const QObject *, const char *,
const char *,
Qt::ConnectionType) const; QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,
const QObject *, PointerToMemberFunction,
Qt::ConnectionType) QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,
Functor);
从上面可以看到,connect函数一共有五个重载的版本,其中各个参数比较之后sender和receiver没有什么区别,都是QObject指针,主要是signal和slot形式的区别。再回到我们的调用回来,我们采用的是第五个重载,当我们的Button发出了clicked信号时,会调用QApplication的quit函数,从而使程序退出。
对于信号和槽的要求是参数保持一致,这里所说的一致是参数类型的一致。如果不一致,可以是槽函数的参数可以比信号的少,而且参数的顺序必须保持一致。
将上述代码稍加修改,使用lambda表达式后我们再来看一下效果。
QObject::connect(&button, &QPushButton::clicked,/*&QApplication::quit*/[](){qDebug()<< "quit"; });
三、QWidget、QDialog及QMainWindow的区别
QWidget类是所有用户界面对象的基类。 窗口部件是用户界面的一个基本单元:它从窗口系统接收鼠标、键盘和其它事件,并且在屏幕上绘制自己。每一个窗口部件都是矩形的,并且它们按Z轴顺序排列。一个窗口部件可以被它的父窗口部件或者它前面的窗口部件盖住一部分。
QMainWindow 类提供一个有菜单条、锚接窗口(例如工具条)和一个状态条的主应用程序窗口。主窗口通常用在提供一个大的中央窗口部件(例如文本编辑或者绘制画布)以及周围 菜单、工具条和一个状态条。QMainWindow常常被继承,因为这使得封装中央部件、菜单和工具条以及窗口状态条变得更容易,当用户点击菜单项或者工具条按钮时,槽会被调用。
QDialog类是对话框窗口的基类。对话框窗口是主要用于短期任务以及和用户进行简要通讯的顶级窗口。QDialog可以是模态对话框也可以是非模态对话框。QDialog支持扩展性并且可以提供返回值。它们可以有默认按钮。QDialog也可以有一个QSizeGrip在它的右下角,使用setSizeGripEnabled()。
QDialog 是最普通的顶级窗口。一个不会被嵌入到父窗口部件的窗口部件叫做顶级窗口部件。通常情况下,顶级窗口部件是有框架和标题栏的窗口(尽管使用了一定的窗口部件标记,创建顶级窗口部件时也可能没有这些装饰。)在Qt中,QMainWindow和不同的QDialog的子类是最普通的顶级窗口。
如果是顶级对话框,那就基于QDialog创建,如果是主窗体,那就基于QMainWindow,如果不确定,或者有可能作为顶级窗体,或有可能嵌入到其他窗体中,则基于QWidget创建。
当然了,实际中,你还可以基于任何其他部件类来派生。看实际需求了,比如QFrame、QStackedWidget等等。
四、自定义信号槽
通过系统提供的connect函数可以让我们连接系统信号和槽,但是你应该会想到我们桐乡可以自己定制自己的信号槽,这也是Qt架构的设计思路,用于我们设计解耦的程序。信号槽不是GUI模块提供的,而是Qt核心特性之一,所以我们同样可以在普通的控制台程序中使用信号槽。
注意:我之所以将头文件和源文件分开来写,是因为moc在我的编译器中必须要将其分开,不然就会报错。
#include<QObject> /////////////////newspaper.h
class Newsspaper :public QObject{ Q_OBJECT
public:
Newsspaper(const QString& name) :m_name(name)
{ }
void send();
signals:
void newPaper(const QString& name);
private:
QString m_name;
};
Newspaper.h
#include "newspaper.h" void Newsspaper::send()
{
emit newPaper(m_name);
}
newspaper.cpp
#include<QObject>
#include<QDebug> class Reader :public QObject
{
Q_OBJECT
public:
Reader();
void receiveNewspaper(const QString& name);
};
reader.h
#include "reader.h" Reader::Reader(){} void Reader::receiveNewspaper(const QString& name)
{
qDebug() << "Receive Newspaper:" << name;
}
reader.cpp
#include "slottest.h"
#include <QtWidgets/QApplication>
#include <QPushButton>
#include <QObject>
#include <QCoreapplication>
#include "newspaper.h"
#include "reader.h" int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Newsspaper newspaper("NewsPaper A");
Reader reader;
QObject::connect(&newspaper,&Newsspaper::newPaper,&reader,&Reader::receiveNewspaper);
newspaper.send(); return a.exec(); }
main.cpp
运行结果:
Receive Newspaper: "NewsPaper A"
根据代码我们对几个重点进行解释:1、Q_OBJECT是Qt的一个宏,能够使程序具有信号槽机制,由moc进行处理,会生成以moc为开头的文件,moc是一种预处理器;2、emit是Qt的另一个宏,用于表示发射信号,使槽函数能够接受信号;3、使用connect函数进行信号槽的连接,槽函数在获取到消息体和信号参数后做出相应,这里就是响应打印消息。4、信号槽的机制类似于广播,可以参照广播模式来理解代码。5、使用 signals 标记信号函数,信号是一个函数声明,返回 void,不需要实现函数代码;6、槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响。
感谢你的耐心阅读,如果有哪些地方错误,请提出来,谢谢!
我的QT5学习之路(四)——信号槽的更多相关文章
- Qt 学习之路 :信号槽
信号槽是 Qt 框架引以为豪的机制之一.熟练使用和理解信号槽,能够设计出解耦的非常漂亮的程序,有利于增强我们的技术设计能力. 所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被 ...
- 我的QT5学习之路(目录)
说明:本目录内容为自己学习的心得和记录,参考资料来源于网络,学习过程中多方汲取,如有错误,欢迎指正和批评. Qt开发相关文章目录 一.我的Qt学习之路系列 1.[笔记]我的Qt学习之路(一)——浅谈Q ...
- 我的QT5学习之路(一)——浅谈QT的安装和配置
一.前言 说到Qt,不能不说到C++,这门伟大的语言.因为其面向对象的编程思想和陡峭的学习曲线,一开始学习起来很是吃力.Qt从QT4开始基本封装了很多C++的工具库和界面库,而且支持跨平台,这是它最大 ...
- Redis——学习之路四(初识主从配置)
首先我们配置一台master服务器,两台slave服务器.master服务器配置就是默认配置 端口为6379,添加就一个密码CeshiPassword,然后启动master服务器. 两台slave服务 ...
- QT学习之深入了解信号槽
槽函数和普通的 C++成员函数没有很大的区别.它们也可以使 virtual 的:可以被重写:可以使 public.protected 或者 private 的:可以由其它的 C++函数调用:参数可以是 ...
- QT学习记录之理解信号槽机制
作者:朱金灿 来源:http://blog.csdn.net/clever101 QT的事件机制采用的信号槽机制.所谓信号槽机制,简而言之就是将信号和信号处理函数绑定在一起,比如一个按钮被单击是一个信 ...
- 我的QT5学习之路(三)——模板库、工具类和控件(下)
一.前言 作为第三篇的最后一部分,我们来看一下Qt的控件,谈到控件,就会让人想到界面的美观性和易操作性,进而想到开发的便捷性.作为windows界面开发的MFC曾经是盛行了多少年,但是其弊端也随着其他 ...
- zigbee学习之路(四):按键控制(中断方式)
一.前言 通过上次的学习,我们学习了如何用按键控制led,但是在实际应用中,这种查询方式占用了cpu的时间,如果通过中断控制就可以解决这个问题,我们今天就来学习按键控制的中断方式. 二.原理分析 传统 ...
- [原创]java WEB学习笔记79:Hibernate学习之路--- 四种对象的状态,session核心方法:save()方法,persist()方法,get() 和 load() 方法,update()方法,saveOrUpdate() 方法,merge() 方法,delete() 方法,evict(),hibernate 调用存储过程,hibernate 与 触发器协同工作
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- bootstrap框架怎么在html页面加载使用
今天敲代码的时候,正好碰到这个问题. 与大家分享这个解决方法: 1/7 到bootstrap官方网站下载,对于我们开发者来说,直接下载编译和压缩后的CSS.JavaScript文件,另外还包含 ...
- Ubuntu,忘记了root密码,怎么重置?
进入单用户模式: 1.开机到grub时,用上下键移到第二行的恢复模式,按e(注意不是回车) 即Ubuntu,With Linux 3.2.0-23-generic(recovery mode) 2.把 ...
- MySQL中有关char、varchar、int、tinyint、decimal
char.varchar属于字符串类型 1.char属于定长,能确切的知道列值的长度,也就是有多少个字符.当指定char(5)时,表示只能存5个字符,如5个英文‘a’,5个汉字‘我’,5个符号‘&am ...
- xml-treeview转换
XML——>treeciew using System; using System.Collections.Generic; using System.Text; using System.Wi ...
- java笔记--正则表达式的运用(包括电话,邮箱验证等)
正则表达式 --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3877402.html "谢谢-- 正则表达式符号:" ...
- SQL点点滴滴_公用表表达式(CTE)递归的生成帮助数据
本文的作者辛苦了,版权问题特声明本文出处:http://www.cnblogs.com/wy123/p/5960825.html 工作有时候会需要一些帮助数据,必须需要连续的数字,连续间隔的时间点,连 ...
- leetcode BFS
1. word ladder class Solution { public: int ladderLength(string beginWord, string endWord, unordered ...
- 机器学习之LinearRegression与Logistic Regression逻辑斯蒂回归(三)
一 评价尺度 sklearn包含四种评价尺度 1 均方差(mean-squared-error) 2 平均绝对值误差(mean_absolute_error) 3 可释方差得分(explained_v ...
- [翻译] ZFTokenField
ZFTokenField 本人视频教程系类 iOS中CALayer的使用 效果图: iOS custom view that let you add token view inside like ...
- @Autowired和@Resource注解的区别
@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false.如果我们想使用按名称装配,可以结合@Qualifier注 ...