一、前言

  前面说了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学习之路(四)——信号槽的更多相关文章

  1. Qt 学习之路 :信号槽

    信号槽是 Qt 框架引以为豪的机制之一.熟练使用和理解信号槽,能够设计出解耦的非常漂亮的程序,有利于增强我们的技术设计能力. 所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被 ...

  2. 我的QT5学习之路(目录)

    说明:本目录内容为自己学习的心得和记录,参考资料来源于网络,学习过程中多方汲取,如有错误,欢迎指正和批评. Qt开发相关文章目录 一.我的Qt学习之路系列 1.[笔记]我的Qt学习之路(一)——浅谈Q ...

  3. 我的QT5学习之路(一)——浅谈QT的安装和配置

    一.前言 说到Qt,不能不说到C++,这门伟大的语言.因为其面向对象的编程思想和陡峭的学习曲线,一开始学习起来很是吃力.Qt从QT4开始基本封装了很多C++的工具库和界面库,而且支持跨平台,这是它最大 ...

  4. Redis——学习之路四(初识主从配置)

    首先我们配置一台master服务器,两台slave服务器.master服务器配置就是默认配置 端口为6379,添加就一个密码CeshiPassword,然后启动master服务器. 两台slave服务 ...

  5. QT学习之深入了解信号槽

    槽函数和普通的 C++成员函数没有很大的区别.它们也可以使 virtual 的:可以被重写:可以使 public.protected 或者 private 的:可以由其它的 C++函数调用:参数可以是 ...

  6. QT学习记录之理解信号槽机制

    作者:朱金灿 来源:http://blog.csdn.net/clever101 QT的事件机制采用的信号槽机制.所谓信号槽机制,简而言之就是将信号和信号处理函数绑定在一起,比如一个按钮被单击是一个信 ...

  7. 我的QT5学习之路(三)——模板库、工具类和控件(下)

    一.前言 作为第三篇的最后一部分,我们来看一下Qt的控件,谈到控件,就会让人想到界面的美观性和易操作性,进而想到开发的便捷性.作为windows界面开发的MFC曾经是盛行了多少年,但是其弊端也随着其他 ...

  8. zigbee学习之路(四):按键控制(中断方式)

    一.前言 通过上次的学习,我们学习了如何用按键控制led,但是在实际应用中,这种查询方式占用了cpu的时间,如果通过中断控制就可以解决这个问题,我们今天就来学习按键控制的中断方式. 二.原理分析 传统 ...

  9. [原创]java WEB学习笔记79:Hibernate学习之路--- 四种对象的状态,session核心方法:save()方法,persist()方法,get() 和 load() 方法,update()方法,saveOrUpdate() 方法,merge() 方法,delete() 方法,evict(),hibernate 调用存储过程,hibernate 与 触发器协同工作

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

随机推荐

  1. OpenStack IceHouse 部署 - 3 - 控制节点部署

    Mysql部署配置  安装 安装mysql,mysql的python绑定 apt-get install mysql-server 安装过程中会要求设定mysql的root账户的密码,这里假定设为my ...

  2. Window ssh免密登录到远程Linux服务器

    SSH采用的是”非对称密钥系统”,即耳熟能详的公钥私钥加密系统. 1. 基于口令的安全验证 这种方式使用用户名密码进行联机登录,一般情况下我们使用的都是这种方式.整个过程大致如下: (1)客户端发起连 ...

  3. js 控制选中文字

     //脚本获取网页中选中文字 var word = document.selection.createRange().text;  //获取选中文字所在的句子 var range =  documen ...

  4. 【HTML&CSS】基本的入门

    在公司培训一段时间不久就去流浪了一段时间,现在回来重新捧起心爱的编程,特别亲切. 自学HTML&CSS,别人说了很多,这那这那的,无论简单还是困难,不亲自去俯下身子学习,怎么都学不会HTML和 ...

  5. 使用input做简单的上传图片

    css 代码: .container{ width: 200px; height: 200px; border: 1px solid #666; } HTML 代码: <input type=& ...

  6. 如何验证一份HTML文档的格式是否正确

    在浏览器中打开 Markup Validation Service . 点击或者激活 Validate by Direct Input 栏. 将整个示范文档的代码(不仅仅是body部分)复制粘贴到在M ...

  7. bat 常见问题及小实例

    bat 常用命令小实例 常见问题: 1.如果你自己编写的.bat文件,双击打开,出现闪退 原因:执行速度很快,执行完之后,自行关闭 解决办法:在最后面一行加上 pause 例如: @echo off ...

  8. App更新之dialog数字进度条

    App更新之dialog数字进度条 前言:现在一般的Android软件都是需要不断更新的,当你打开某个app的时候,如果有新的版本,它会提示你有新版本需要更新.当有更新时,会弹出一个提示框,点击下载, ...

  9. CentOS下二进制包/源码安装方式的MySQL卸载步骤

    查看当前系统mysql 运行状态 [root@zendlinux ~]# ps -ef |grep mysql root 1153 1 0 15:40 ? 00:00:00 /bin/sh /usr/ ...

  10. 一些baidu面经

    百度问的一些问题供参考: 1. epoll 和 select,epoll 两种模式,阻塞非阻塞: 2. 两个严格递增链表找出相同的元素组成新的链表: ref1   ref 3. 网络传输中如何传送一个 ...