一   信号和槽

  GUI 程序除了要绘制控件,还要响应系统和用户事件,例如重绘、绘制完成、点击鼠标、敲击键盘等。当事件发生时,UI 会产生相应的变化,让用户直观地看到。
大部分编程(例如Win SDK、Web前端)中使用回调函数来响应事件,而 Qt 却独创了信号和槽机制。所谓回调函数,就是程序员提前定义一个函数,当事件发生时就调用该函数。
信号和槽是Qt的核心,它让两个互不相干的对象连接起来,当一个对象的状态改变时,可以通知另一个对象。
我们先通过例子来演示一下信号和槽:

具体的代码:

#include "mainwindow.h"
#include <QApplication>
#include <QMainWindow>
#include <QLabel>
#include <QPushButton>
#include <QLineEdit>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QMainWindow w;
    w.setWindowTitle("微浪游戏");
    w.resize(325, 120);

    QLineEdit lineEdit(&w);
    lineEdit.setGeometry(30, 20, 180, 36);
    lineEdit.setPlaceholderText("请输入文本");

    QPushButton btn("取消", &w);
    btn.setGeometry(220, 20, 70, 36);

    QLabel label(&w);
    label.setGeometry(30, 70, 250, 30);

    //连接clicke()信号和quit()槽
    QObject::connect(&btn, SIGNAL(clicked()), &app, SLOT(quit()));
    //连接textChanged()信号和setText()槽
    QObject::connect(&lineEdit, SIGNAL(textChanged(QString)), &label, SLOT(setText(QString)));

    w.show();
    return app.exec();
}

在上面的demo中创建了三个控件:lineEdit,btn,label,他们都是QMainWindow w的子控件。运行的结果如下:

点击“取消”按钮,程序就关闭了,这是第26行代码的作用;在文本输入框中输入一段文本,下面的 Label 会随时显示出来,这是第28行代码的作用。

这两个对象都是通过信号和槽连接起来的,信号和槽用于两个对象之间的通信。信号和槽是QT的核心特征,当一个特殊的事情发生时便可以发射一个信号,比如demo中的取消按钮被点击时,就会发射clicked()信号;而槽就是一个函数,它在信号发射后被调用来响应这个信号,Qt的部件类中已经定义了一些信号和槽,但是更常用的做法是子类化部件,然后添加自定义的信号和槽来实现想要的功能。

信号是只有函数声明、没有函数体的成员函数。槽是拥有完整函数体的普通成员函数,你可以在槽函数中实现各种功能,与普通函数相比并没有区别,例如 quit() 的作用就是退出程序。

connect() 是 QObject 类的静态成员函数;QObject 是 Qt 中所有类的基类,它就像“树根”,从这里派生出了所有其他“树枝”。
需要注意的是,信号不是事件。当用户点击“取消”按钮时,Qt 会捕获该点击事件,进行预处理,然后发射 clicked() 信号; clicked() 和 quit() 关联起来了,接下来就会调用 quit() 函数。
信号和槽机制归根结底也是回调函数,只不过绕了个圈子。在这种机制下,程序员有两次处理事件的机会,一是在捕获事件后发射信号前进行预处理(事件不符合预期可以不发射信号),二是在槽函数中进行主要处理。
再来看第27行。textChange() 信号会在文本改变时发出,setText() 槽用来设置 Label 的文本,QString
是要传递的数据的类型。当用户输入文本时,lineEdit 会发出 textChange() 信号,该信号将携带数据,数据类型为
QString,数据内容为输入的文本;setText() 槽接收到信号后先解析信号携带的数据,获取用户输入的文本,然后填充到 Label 中。

二 信号和槽的关联

信号和槽的关联使用的是QObject类的connect()函数,connect() 是 QObject 类的静态成员函数,它有多个原型:

connect(QObject *sender,   char *signal,
        QObject *receiver, char *method);
connect(QObject *sender,   PointerToMemberFunction signal,
        QObject *receiver, PointerToMemberFunction method);
connect(QObject *sender,   PointerToMemberFunction signal,
        QObject *context,  Functor functor);
connect(QObject *sender,   QMetaMethod &signal,
        QObject *receiver, QMetaMethod &method);
connect(QObject *sender,   PointerToMemberFunction signal,  Functor functor);

简单起见,上面省略了 connect() 的返回值和最后一个参数,以及某些参数前面的 const 修饰符,读者可以在 Qt 帮助手册中查看完整的原型。

connect() 函数返回值类型为QMetaObject::Connection,表示当前连接句柄。最后一个参数为Qt::ConnectionType type = Qt::AutoConnection,表示连接类型,一般默认即可。

观察上面的原型,除了最后一个有3个参数,其他都有4个参数,其中:
1) sender 为信号发送者,receiver 为信号接收者,它们都是对象指针。

2) 第1个原型中,signal 为信号,method 为槽函数,它们都是字符串,必须借助 SIGNAL() 和 SLOT()
将函数形式转换为字符串形式。SIGNAL() 和 SLOT() 是宏,而非函数。上面的示例中就使用了该原型,它是常用的原型,初学者必须要掌握。

3) 第2个原型中,PointerToMemberFunction 为指向成员函数的指针。你可以将示例中的代码做如下更改:

QObject::connect(&btn, &QPushButton::clicked, &app, &QApplication::quit);
QObject::connect(&lineEdit, &QLineEdit::textChanged, &label, &QLabel::setText);

这是 Qt 5 新增的原型,可以在编译期间进行检查,如果信号和槽不存在或者不匹配,则会报错。而第1种原型是从 Qt 诞生以来一直支持的,不能在编译期进行检测,如果信号和槽有误,只会在程序运行期间给出警告并返回 false,不容易发现问题,这是它的一个缺陷。所以在 Qt 5 中我们鼓励使用第2种原型。

QT Creator 快速入门教程 读书笔记(三)的更多相关文章

  1. QT Creator 快速入门教程 读书笔记(一)

    一 Qt简介 Qt 是一个跨平台的C++应用程序框架,支持Windows.Linux.Mac OS X.Android.iOS.Windows Phone.嵌入式系统等.也就是说,Qt 可以同时支持桌 ...

  2. QT Creator 快速入门教程 读书笔记(二)

    一 窗口部件 基础窗口部件QWidget类是所有用户界面对象的基类,窗口和控件都是直接或间接继承自 QWidget,下面我们来看一个很简单的例子: 窗口部件(Widget)简称部件,是QT中建立界面的 ...

  3. [Qt Creator 快速入门] 第1章 Qt Creator简介

    Qt Creator 是一个跨平台的.完整的 Qt 集成开发环境,其中包括了高级C++代码编辑器.项目和生成管理工具.集成的上下文相关的帮助系统.图形化调试器.代码管理和浏览工具等.这一章先对 Qt ...

  4. [Qt Creator 快速入门] 第2章 Qt程序编译和源码详解

    一.编写 Hello World Gui程序 Hello World程序就是让应用程序显示"Hello World"字符串.这是最简单的应用,但却包含了一个应用程序的基本要素,所以 ...

  5. [Qt Creator 快速入门] 第5章 应用程序主窗口

    对于日常见到的应用程序而言,许多都是基于主窗口的,主窗口中包含了菜单栏.工具栏.状态栏和中心区域等.这一章会详细介绍主窗口的每一个部分,还会涉及资源管理.富文本处理.拖放操作和文档打印等相关内容.重点 ...

  6. [Qt Creator 快速入门] 第0篇 开始学习Qt 与Qt Creator

    Qt官方信息 Qt官网:http://qt.digia.com/ Qt开源官网:http://qt-project.org/ Qt最新版本下载:http://qt-project.org/downlo ...

  7. [Qt Creator 快速入门] 第8章 界面外观

    一个完善的应用程序不仅应该有实用的功能,还要有一个漂亮的外观,这样才能使应用程序更加友好,更加吸引用户.作为一个跨平台的UI开发框架,Qt提供了强大而灵活的界面外观设计机制.这一章将学习在Qt中设计应 ...

  8. [Qt Creator 快速入门] 第3章 窗口部件

    从这一章开始正式接触Qt的窗口部件.在第2章曾看到 Qt Creator 提供的默认基类只有 QMainWindow.QWidget 和 QDialog 这3种.QMainWindow 是带有菜单栏和 ...

  9. [Qt Creator 快速入门] 第9章 国际化、帮助系统和Qt插件

    一.国际化 国际化的英文表述为Internationalization,通常简写为I18N(首尾字母加中间的字符数),一个应用程序的国际化就是使该应用程序可以让其他国家的用户使用的过程. Qt支持现在 ...

随机推荐

  1. CentOS下WDCP下的MYSQL开启远程连接

    1.首先要在防火墙开启3306端口访问 2.然后做如下操作 如何开启MySQL的远程帐号-1)首先以 root 帐户登陆 MySQL 在 Windows 主机中点击开始菜单,运行,输入"cm ...

  2. Python学习一:Python简介

    Python简介: Python是目前广泛使用的一门动态语言,类似Java,源代码必须首先由编译器转换成字节码(byte code),然后再由解释器来执行字节码.与Java不同的是,Python的编译 ...

  3. phpcms v9更改后台文章排序的方法

    后台文章排序怎么才可以按自己输入的数字排列?如按4,3,2,1,从大到小排列?实现方法如下: 修改文件: phpcms\modules\content 中的 content.php 代码如下: $da ...

  4. 关于OpenGL和DX学习的取舍

    大家多知道左右就肯定要与显卡打交道.两大图形图像IPA.OpenGL(图形),DX(图形,声音,键盘控制,网络) OpenGL的兴起可能取决于苹果公司的适用,吸引看大部分开发者适用,它有跨平台的有点. ...

  5. nodejs中异步

    nodejs中的异步 1 nodejs 中的异步存在吗? 现在有点 javascript 基础的人都在听说过 nodejs ,而只要与 javascript 打交到人都会用或者是将要使用 nodejs ...

  6. HTML第一课

    <标签名 属性>内容</标签名> <标签/> 静态网页与动态网页的区别:是否从数据库提取数据相对路径跟绝对路径../代表高一级的&nbsp牛逼的空格< ...

  7. Laravel事件Event

    适用场景:记录文章浏览量 php artisan make:event 事件名 示例: php artisan make:event MyEvent Laravel目录\app\Events已经生成M ...

  8. 10条建议让你创建更好的jQuery插件

    在开发过很多 jQuery 插件以后,我慢慢的摸索出了一套开发jQuery插件比较标准的结构和模式.这样我就可以 copy & paste 大部分的代码结构,只要专注最主要的逻辑代码就行了.使 ...

  9. JavaScript设计模式之构造器、模块和原型

    JavaScript面向对象 JavaScript是一种无类语言,但可以使用函数来模拟,这就涉及到设计模式.模式是一种已经验证过的可复用的解决方案,可用于解决软件设计中遇到的常见的问题,通常将这些解决 ...

  10. .NET学习路线图

    文章转载自「开发者圆桌」一个关于开发者入门.进阶.踩坑的微信公众号 你可以通过百度云盘下载.NET学习路线图相关视频资源 链接: http://pan.baidu.com/s/1pL2gCK7 密码: ...