信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性。当某个信号被发射,就需要调用与之相绑定的槽函数。这与Windows下的消息机制类似,消息机制是基于回调函数。一个回调即是一个函数的指针,因此如果希望一个处理函数通知一些事件,可以传递一个函数(回调函数)的指针给这个处理函数。这个处理函数就会在适当的时候调用回调函数。但是回调函数有两大缺点:第一,它们不是类型安全的。我们从来不敢确定处理函数会用正确的参数来调用回调函数;第二,回调函数被强力和处理函数联系着,因为处理函数必须知道去调用哪个回调函数。

信号和槽的机制是类型安全的:一个信号的签名必须与接收槽的签名相匹配。(实际上一个槽可能有一个比它所接收到的信号的签名更短的签名因为它能够忽略额外的参数。)因为签名是一致的,所以编译器能够帮助我们发现类型不匹配。信号和槽是松散的联系在一起的:一个发射信号的类从来不知道也不关心哪个槽接收这个信号。Qt的信号和槽机制确保如果你将一个信号和一个槽连接起来,这个槽将在正确的时间被用这个信号的参数所调用。信号和槽可以带任何数量任何类型的参数。它们完全是类型安全的。

信号(Signals)

当对象改变其状态时,信号就由该对象发射 (emit) 出去,而且对象只负责发送信号,它不知道另一端是谁在接收这个信号。这样就做到了真正的信息封装,能确保对象被当作一个真正的软件组件来使用。

信号只需要在头文件中进行声明,不需要在cpp中实现。放在Qt自定义关键字signals下,在此之前一定要加上Q_OBJECT宏。

在编程中,一般使用的是控件内部定义好的信号。如:QTreeWidget类下的 Signals:

  1. void currentItemChanged ( QTreeWidgetItem * current, QTreeWidgetItem * previous );
  2. void itemActivated ( QTreeWidgetItem * item, int column );
  3. void itemChanged ( QTreeWidgetItem * item, int column );
  4. void itemClicked ( QTreeWidgetItem * item, int column );
  5. void itemCollapsed ( QTreeWidgetItem * item );
  6. void itemDoubleClicked ( QTreeWidgetItem * item, int column );
  7. void itemEntered ( QTreeWidgetItem * item, int column );
  8. void itemExpanded ( QTreeWidgetItem * item );
  9. void itemPressed ( QTreeWidgetItem * item, int column );
  10. void itemSelectionChanged ();

也可以自定义信号,并通过emit在代码中发射信号。

  1. class sender : public QObject
  2. {
  3. Q_OBJECT
  4.  
  5. public:
  6. void doSend();
  7. signals:
  8. void send(int);
  9. };
  10. // ------------ sender.cpp -----------
  11. #include "sender.h"
  12. void sender :: doSend()
  13. {
  14. emit send();
  15. }

槽函数(Slots)

槽和普通的C++成员函数几乎是一样的(可以是虚函数,可以被重载,可以是public slots、protected slots、private slots,可以被其他C++成员函数直接调用;唯一不同的是:槽还可以和信号连接在一起,在这种情况下,信号被发射时,会自动调用这个槽。)槽不需要信号传过来的参数时,可以不要参数;但槽一旦要参数,其参数个数,类型,顺序必须要和对应的信号保持一致。另外,槽的参数不能有缺省值。

  1. class receiver : public QObject
  2. {
  3. Q_OBJECT
  4.  
  5. public slots:
  6. //带有参数的槽函数,需和绑定的信号的参数保持一致
  7. void recv(int);
  8. };
  9. // ------------ Receiver.cpp -----------
  10. void receiver :: recv(int n)
  11. {
  12. qDebug()<<"recv number: "<<n<<endl;
  13. }

关联信号和槽(connect)

可以使用QObject类的静态成员函数connect来建立信号的槽的关联

  1. bool QObject::connect (const QObject * sender, const char * signal, const QObject * receiver, const char * slot) [static]

具体的调用为:connect(sender, SIGNAL(signal), receiver, SLOT(slot)); 其中sender和receiver为QObject类对象的指针; SIGNAL宏和SLOT宏将信号的槽转换成字符串。

  1. sender s;
  2. receiver r;
  3. QObject::connect(&s, SIGNAL(send(int)), &r, SLOT(recv(int)));

注:在connect函数中信号函数和槽函数若有参数,只能写出参数类型,而不能也将变量名写出;否则,连接会失败!

  • 一个信号可以连接多个槽

当信号发射时,会以不确定的顺序一个接一个的调用各个槽。

  • 多个信号可以连接同一个槽

即无论是哪一个信号被发射,都会调用这个槽。

  • 信号直接可以相互连接

发射第一个信号时,也会发射第二个信号。

断开信号和槽(disconnect)

当信号和槽没有必要继续保持连接时,可以通过调用disconnect来断开它们。

  1. bool QObject::disconnect (const QObject * sender, const char * signal, const Object * receiver, const char * slot) [static]

有三种情况必须使用 disconnect() 函数:

(1)断开与某个对象相关联的任何对象。

  1. disconnect(sender, , , ) ;
  2. //或者
  3. sender->disconnect();

(2)断开与某个特定信号的任何关联。

  1. disconnect(sender, SIGNAL(signal()), , );
  2. //或者
  3. sender->disconnect(SIGNAL(signal()));

(3)断开两个对象之间的关联。

  1. disconnect(sender, , receiver, );
  2. //或者
  3. sender->disconnect(receiver);

应注意的问题

  1. 信号与槽机制与普通函数的调用一样,如果使用不当的话,在程序执行时也有可能产生死循环。因此,在定义槽函数时一定要注意避免间接形成无限循环,即在槽中再次发射所接收到的同样信号。例如 , 在前面给出的例子中如果在 mySlot() 槽函数中加上语句 emit mySignal() 即可形成死循环。
  2. 如果一个信号与多个槽相联系的话,那么,当这个信号被发射时,与之相关的槽被激活的顺序将是随机的。
  3. 宏定义不能用在 signal 和 slot 的参数中。
  4. 信号和槽的参数个数与类型必须一致。

Qt 信号和槽函数的更多相关文章

  1. QT信号和槽函数学习笔记

    //connect 函数有4个参数 分别是 发送者 信号.接受者 ,槽 //connect(sender,signal,receiver,slot) /* * 信号和槽 * 信号 就是一个普通的函数 ...

  2. QT+信号和槽函数_自定义槽函数_一个信号对应多个槽函数

    以下的代码里面有自定义槽函数的内容,同时也有信号实现的函数: #ifndef MAINWIDGET_H #define MAINWIDGET_H #include <QWidget> #i ...

  3. qt的信号与槽函数

    关联: bool connect ( const?QObject?*?sender, const?char?*?signal, const QObject * receiver, const char ...

  4. 【QT】无需写connect代码关联信号和槽函数

    对于一些简单的事件判别,如点击按钮. 无需写代码关联信号和槽函数. connect(ui->Btnshowhello,SIGNAL(clicked(bool)),this,SLOT(Btnsho ...

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

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

  6. QT 信号与槽connect

    QT 信号与槽connect QT 信号与槽connect connect函数调用几个限制 connect函数代码 QT中信号与槽的连接使用的connect函数是一个静态函数,在类QObject中定义 ...

  7. QT 信号与槽连接

    转帖 http://www.cnblogs.com/cnhome/archive/2009/10/01/1577277.html 信号(SIGNAL)和槽(SLOT)是Qt编程的一个重要部分.这个机制 ...

  8. Qt 信号与槽

    Qt信号与槽的理解 信号和槽机制是 QT 的核心机制,要精通 QT 编程就必须对信号和槽有所了解.信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重 ...

  9. QT 信号与槽 QT简单加法器的实现

    信号与槽 背景: 面向过程 模块之间低耦合设计(高内聚). 函数调用: 直接调用 回调调用(低耦合) 面向对象 模块之间低耦合设计(高内聚) 对象调用 直接调用 接口调用 QT: 信号与槽解决问题: ...

随机推荐

  1. Java利用MessageDigest提供的MD5算法加密字符串或文件

    MD5是常用的加密算法,也经常用于校验信息完整,如文件的完整性.用术语讲,MD5是一种消息摘要算法(Message Digest Algorithm).另外还有一种常用的消息摘要算法SHA1.如果想了 ...

  2. 用widthStep的方法来增加某范围的像素----与imageROI对比

    //用widthStep的方法来增加某范围的像素 //作者:sandy //时间:2015-10-5 #include <cv.h> #include <highgui.h> ...

  3. 在单线程中你最好使用ArrayList而不是Vector

    <java核心技术卷一>571页上提到Vector类的所有方法都是同步的.可以由两个线程安全地访问同一个Vector对象.显然,如果可以确定我们不会在多个线程中对这个数组进行操作的话,我们 ...

  4. 转--2014年最新810多套android源码2.46GB免费一次性打包下载

    转载自:http://www.eoeandroid.com/thread-497046-1-1.html 感谢该博客主人无私奉献~~ 下面的源码是从今年3月份开始不断整理源码区和其他网站上的安卓例子源 ...

  5. 树莓派,使用opencv调用自带的摄像头

    OpenCV&Pi Cam – Step 1 : Install It’s quite easy to install your new Pi Camera. Installation pro ...

  6. Java基础-事件处理

  7. Dede cms文章内容管理系统安全漏洞!如何有效防止DEDE织梦系统被挂木马安全设置

    第一.安装Dede的时候数据库的表前缀,最好改一下,不要用dedecms默认的前缀dede_,可以改成ljs_,随便一个无规律的.难猜到的前缀即可. 第二.后台登录一定要开启验证码功能,将默认管理员a ...

  8. [ActionScript 3.0] AS3中的位图(BitmapData)应用

    1.位图使用(模糊)滤镜 //创建一个矩形区域的BitmapData var bmd:BitmapData = new BitmapData(80, 30, false, 0xffffff); //画 ...

  9. poj 1753 Flip Game

    点击打开链接 Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 25674   Accepted: 1109 ...

  10. WayPoint寻路

    寻路在游戏开发中的重要性,不用多说了.从大型ARPG游戏到小规模体验游戏,都会不同程度的用到寻路功能. 塔防类游戏,战棋类游戏经常用到waypoint(路径)寻路. 下面我们来介绍一下waypoint ...