From: http://blog.csdn.net/rl529014/article/details/51346955

GUI 程序除了要绘制控件,还要响应系统和用户事件,例如重绘、绘制完成、点击鼠标、敲击键盘等。当事件发生时,UI 会产生相应的变化,让用户直观地看到。

大部分编程(例如Win SDK、Web前端)中使用回调函数来响应事件,而 Qt 却独创了信号和槽机制。

所谓回调函数,就是程序员提前定义一个函数,当事件发生时就调用该函数。

信号和槽是 Qt 的核心,它让两个互不相干的对象连接起来,当一个对象的状态改变时,可以通知另一个对象。

我们先通过例子来演示一下信号和槽:

新建一个Qt应用程序

 

注意,最后一定要选择去掉“创建界面”复选框。

 

在main.cpp中添加代码:

源代码如下:

  1. #include "mainwindow.h"
  2. #include <QApplication>
  3. #include <QMainWindow>
  4. #include <QLabel>
  5. #include <QPushButton>
  6. #include <QLineEdit>
  7. int main(int argc, char *argv[])
  8. {
  9. QApplication app(argc, argv);
  10. QMainWindow w;
  11. w.setWindowTitle("Widgets工程");
  12. w.resize(325, 120);
  13. QLineEdit lineEdit(&w);
  14. lineEdit.setGeometry(30, 20, 180, 36);
  15. lineEdit.setPlaceholderText("请输入文本");
  16. QPushButton btn("取消", &w);
  17. btn.setGeometry(220, 20, 70, 36);
  18. QLabel label(&w);
  19. label.setGeometry(35, 60, 250, 30);
  20. //连接clicke()信号和quit()槽
  21. QObject::connect(&btn, SIGNAL(clicked()), &app, SLOT(quit()));
  22. //连接textChanged()信号和setText()槽
  23. QObject::connect(&lineEdit, SIGNAL(textChanged(QString)), &label, SLOT(setText(QString)));
  24. w.show();
  25. return app.exec();
  26. }

该代码中创建了三个控件,一个文本输入框(LineEdit)、一个按钮(PushButton)和一个Label,他们都是主窗口 w 的子对象。

运行结果:

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

先关注第25行代码。clicked() 是按钮 btn 的信号,quit() 是 app 的槽,connect() 函数将它们连接起来,就像“楔子”插入“凹槽”中。用户点击按钮时会发出 clicked() 信号,然后由 quit() 槽接收并关闭程序。

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

connect() 是 QObject 类的静态成员函数;QObject 是 Qt 中所有类的基类,它就像“树根”,从这里派生出了所有其他“树枝”。

需要注意的是,信号不是事件。当用户点击“取消”按钮时,Qt 会捕获该点击事件,进行预处理,然后发射 clicked() 信号; clicked() 和 quit() 关联起来了,接下来就会调用 quit() 函数。

信号和槽机制归根结底也是回调函数,只不过绕了个圈子。在这种机制下,程序员有两次处理事件的机会:

一是在捕获事件后发射信号前进行预处理(事件不符合预期可以不发射信号)。

二是在槽函数中进行主要处理。

再来看第27行。textChange() 信号会在文本改变时发出,setText() 槽用来设置 Label 的文本,QString 是要传递的数据的类型。

当用户输入文本时,lineEdit 会发出 textChange() 信号,该信号将携带数据,数据类型为 QString,数据内容为输入的文本;

setText() 槽接收到信号后先解析信号携带的数据,获取用户输入的文本,然后填充到 Label 中。

 

关于 connect()

connect() 是 QObject 类的静态成员函数,它有多个原型:

  1. connect(QObject *sender,   char *signal,  QObject *receiver, char *method);
  2. connect(QObject *sender,   PointerToMemberFunction signal, QObject *receiver, PointerToMemberFunction method);
  3. connect(QObject *sender,   PointerToMemberFunction signal, QObject *context,  Functor functor);
  4. connect(QObject *sender,   QMetaMethod &signal, QObject *receiver, QMetaMethod &method);
  5. 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][转载] Qt信号和槽的更多相关文章

  1. Qt学习之信号与槽(一)

    Qt学习之信号与槽(一) 目录 QT的信号与槽机制 在窗口的UI设计中操作添加信号和槽     QT的信号与槽机制   QT的两种机制 在Qt和PyQt中有两种通信机制: 低级事件处理机制(low-l ...

  2. Qt学习笔记----信号与槽实现的四种方式

    1.以按钮为例,首先添加一个按钮,对象名为pushButton,在按钮是右键单击选择“转到槽”即可,在转到槽选择面板(右图)里面选择需要进行的操作,比如单击clicked() 2.选择菜单“编辑”,找 ...

  3. Qt入门之信号与槽机制

    一. 简介 就我个人来理解,信号槽机制与Windows下消息机制类似,消息机制是基于回调函数,Qt中用信号与槽来代替函数指针,使程序更安全简洁. 信号和槽机制是 Qt 的核心机制,可以让编程人员将互不 ...

  4. Qt中使用信号和槽的一点心得

    信号(Signal)与槽(Slot)-Qt中的典型机制 这一篇文章中都说得很详细了,这里不再重复,只说一点在实际使用中可能会遇到的问题. 1.一个信号不要同时连接几个槽函数,不然执行的顺序是随机的,最 ...

  5. Qt编程之信号与槽-------unresolved external symbol "public: virtual struct QMetaObject const * __thiscall XX::metaObject(void)const

    原因是加入Q_OBJECT这个macro的类,被编译的时候就要用到moc这个命令,所以在VS2010中,没有加入此命令的应用,当然会出错了.所以解决办法是加,或者如果你不使用信号槽可以直接删除. 当要 ...

  6. qt学习:信号,槽

    [C.GUI.Qt.4编程(第二版)](加)布兰切特,(英)萨默菲尔德.扫描版[学习库www.xuexi111.com].pdf 信号和槽是Qt编程的基础,它可以让各种对象联系在一起. 1. 使用co ...

  7. Qt 5中信号和槽的新语法

    QT 是一个跨平台的 C++ GUI 应用构架,它提供了丰富的窗口部件集,具有面向对象.易于扩展.真正的组件编程等特点,更为引人注目的是目前 Linux 上最为流行的 KDE 桌面环境就是建立在 QT ...

  8. 【QT学习】信号和槽机制

    QT中发射信号使用 emit 来完成. 类要使用信号和槽机制,必须从QObject或者QObject子类继承.必须在类的定义中加上 Q_OBJECT 宏. 信号和槽连接时,参数类型必须相同. 关键字大 ...

  9. Qt之自定义信号和槽函数

    自定义信号和槽函数: 1.类的声明和实现分别放在.h和.cpp文件中: 2.类声明包含Q_OBJECT宏: 3.信号只要声明不要设计其的实现函数 4.发射信号用emit关键字 5.自定义槽的实现与普通 ...

随机推荐

  1. Spring框架学习之IOC(一)

    Spring框架学习之IOC(一) 先前粗浅地学过Spring框架,但当时忙于考试及后期实习未将其记录,于是趁着最近还有几天的空闲时间,将其稍微整理一下,以备后期查看. Spring相关知识 spri ...

  2. C语言预处理命令之条件编译(#ifdef,#else,#endif,#if等)

    转自:http://www.kuqin.com/language/20090806/66164.html 预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器.可见预处理过程先于编译器 ...

  3. linux命令(6/10):find 命令

    Linux将时钟分为系统时钟(System Clock)和硬件(Real Time Clock,简称RTC)时钟两种.系统时间是指当前Linux Kernel中的时钟, 而硬件时钟则是主板上由电池供电 ...

  4. Windows Server 2008 R2 FTP无法从外部访问的解决方法

    在Windows Server 2008 R2中配置好FTP服务器后,可以在本机访问,但是无法从另一台电脑访问.原因就是在于防火墙没有配置好. 1.首先检查服务器管理器中的入站规则,确保已启用FTP服 ...

  5. 配置zabbix通过微信报警企业微信报警

    如今势态: 报警的方式可谓是八仙过海各显神通,如电话报警,短信报警,邮件报警,QQ报警,微信报警等等. 电话报警:一般都是使用别的平台的工具,平台给你提供一个接口供你使用,大多数为限量收费款 短信报警 ...

  6. sql行列互换

    出现这个结果: sql如下: end) as erjidu from a GROUP BY y;

  7. 服务器状态监控之snmp&ipmi

    一.ipmi 1.简介 IPMI(Intelligent Platform Management Interface)即智能平台管理接口是使硬件管理具备"智能化"的新一代通用接口标 ...

  8. UniquePaths,UniquePaths2,路径问题。动态规划。

    UniquePaths:给定m*n矩阵,从(0,0)到(m-1,n-1)路径条数.只能向下向右走. 算法分析:这和爬楼梯问题很像,到(m,n)的路径数是到(m-1,n)和(m,n-1)路径和.第一行, ...

  9. 微信app支付java后台流程、原理分析及nei网穿透

    一.流程步骤 本实例是基于springmvc框架编写 1.执行流程           当手机端app(就是你公司开发的app)在支付页面时,调起服务端(后台第1个创建订单接口)接口,后台把需要调起微 ...

  10. 求中位数,O(n)的java实现【利用快速排序折半查找中位数】

    查找无序数组的中位数,要想时间复杂度为O(n)其实用计数排序就能很方便地实现,在此讨论使用快速排序进行定位的方法. 1.中位数定义 2.算法思想 3.Java代码实现 4.时间复杂度分析 5.附录 中 ...