Qt的信号槽机制介绍(含Qt5与Qt4的差异对比)

转载地址:

https://blog.csdn.net/nicai888/article/details/51169520

 闲谈:

        熟悉Window下编程的小伙伴们,对其消息机制并不陌生, 话说:一切皆消息。它可以很方便实现不同窗体之间的通信,然而MFC库将很多底层的消息都屏蔽了,尽管使用户更加方便、简易地处理消息,但也让人特别是没有Win32编程基的人感到迷茫,不是为何,笔者也是深受其害的。

        详细描述就不在此展开,感兴趣的请查阅浩瀚如海的资料。。。


二 简要介绍:

        基于Qt开发,信号槽是确保正常通信的主要机制,特别是在多线程开发中,线程函数与界面的通信是无法直接进行的,会存在程序崩溃的问题,笔者在实际开发过程中也遇到过此问题,利用Qt的信号槽机制可以避免。

        所谓信号槽,类似于设计模式中的观察者模式。当某一事件发生之后,比如,点击了一下PushButton,它就会发出一个信号(signal)。需注意,这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,可以使用连接(connect)函数进行两者之间的关联,即:发送者发送信号(signal),接收者(感兴趣对象)用自己的一个函数(称之为槽(slot))来处理这个信号。同观察者一样,一个signal可以关联(注册)多个slot,当信号发出时,被连接的槽函数会自动被回调。

        connect()函数是信号槽机制的关键,下面介绍。


三 connect()函数:

        Qt5与Qt4中对connect()函数的实现有所差异。

        首先,看Qt4对其实现的定义:

[cpp]  view plain  copy
  1. bool connect(const QObject *, const char *,  
  2.              const QObject *, const char *,  
  3.              Qt::ConnectionType);  
  4.    
  5. bool connect(const QObject *, const QMetaMethod &,  
  6.              const QObject *, const QMetaMethod &,  
  7.              Qt::ConnectionType);  
  8.    
  9. bool connect(const QObject *, const char *,  
  10.              const char *,  
  11.              Qt::ConnectionType) const  
       介绍定义1,参数分别为:发送者sender信号signal接收者receiver槽slot,最后一个基本不用。sender 类型是const QObject *,signal 的类型是const char *,receiver 类型是const QObject *,slot 类型是const char *。这个函数将 signal 和 slot 作为字符串处理。

        Qt4使用了SIGNAL和SLOT这两个宏,将信号和槽的函数名转换成了字符串。注意,不能将全局函数或者 Lambda 表达式传入connect()。使用字符串导致了Qt4有以下缺点:一旦出现连接不成功的情况,Qt 4 是没有编译错误的(因为一切都是字符串,编译期是不检查字符串是否匹配),而是在运行时给出错误。这无疑会增加程序的不稳定性。

        下面,看Qt5对其实现的定义:

[cpp]  view plain  copy
  1. QMetaObject::Connection connect(const QObject *, const char *,  
  2.                                 const QObject *, const char *,  
  3.                                 Qt::ConnectionType);  
  4.    
  5. QMetaObject::Connection connect(const QObject *, const QMetaMethod &,  
  6.                                 const QObject *, const QMetaMethod &,  
  7.                                 Qt::ConnectionType);  
  8.    
  9. QMetaObject::Connection connect(const QObject *, const char *,  
  10.                                 const char *,  
  11.                                 Qt::ConnectionType) const;  
  12.    
  13. QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,  
  14.                                 const QObject *, PointerToMemberFunction,  
  15.                                 Qt::ConnectionType)  
  16.    
  17. QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,  
  18.                                 Functor);  
        第一个,sender 类型是const QObject *,signal 的类型是const char *,receiver 类型是const QObject *,slot 类型是const char *。这个函数将 signal 和 slot 作为字符串处理,与Qt4相同,应该是为了兼容性而予以保留的。

        第二个,sender 和 receiver 同样是const QObject *,但是 signal 和 slot 都是const QMetaMethod &。我们可以将每个函数看做是QMetaMethod的子类。因此,这种写法可以使用QMetaMethod进行类型比对。

        第三个,sender 同样是const QObject *,signal 和 slot 同样是const char *,但是却缺少了 receiver。这个函数其实是将 this 指针作为 receiver,与Qt4相同,应该是为了兼容性而予以保留的

        第四个,sender 和 receiver 也都存在,都是const QObject *,但是 signal 和 slot 类型则是PointerToMemberFunction。看这个名字就应该知道,这是指向成员函数的指针。

       第五个,前面两个参数没有什么不同,最后一个参数是Functor类型。这个类型可以接受 static 函数、全局函数以及 Lambda 表达式

       Qt5相比较于Qt4的优势是添加了第4和第5种的重载形式,使得Qt可以在编译期进行错误检查,及早发现问题。


在下一篇文章中将根据实际代码简要介绍信号槽的使用

猜你喜欢

转载自blog.csdn.net/qq78442761/article/details/80653472