> 文档中心 > QT之connect的第五个参数(信号与槽的使用)

QT之connect的第五个参数(信号与槽的使用)


一 、QT connect 第5个参数一般不填,为默认值。

1、Qt::AutoConnection: 默认值,使用这个值则连接类型会在信号发送时决定。如果接收者和发送者在同一个线程,则自动使用Qt::DirectConnection类型。如果接收者和发送者不在一个线程,则自动使用Qt::QueuedConnection类型。

  2、Qt::DirectConnection函数会在信号发送的时候直接被调用,槽函数和信号发送者在同一线程。效果看上去就像是直接在信号发送位置调用了槽函数,效果上看起来像函数调用,同步执行。
emit语句后面的代码将在与信号关联的所有槽函数执行完毕后才被执行。

无论槽函数所属对象在哪个线程,槽函数都在发射信号的线程内执行。

  3、Qt::QueuedConnection信号发出后,信号会暂时被放到一个消息队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,然后执行和信号关联的槽函数,这种方式既可以在同一线程内传递消息也可以跨线程操作。

emit语句后的代码将在发出信号后立即被执行无需等待槽函数执行完毕

槽函数在接收者所依附线程执行。

4、Qt::BlockingQueuedConnection槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞直到槽函数运行完。而且接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。

  5、Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是为了避免重复连接。

一般qt connect的第五个参数会在多线程中运用到,需要注意的是:

QThread是用来管理线程的,QThread对象所依附的线程和所管理的线程并不是同一个概念。QThread所依附的线程,就是创建QThread对象的线程;QThread 所管理的线程,就是run启动的线程,也就是新建线程

例如:QThread对象依附在主线程中,QThread对象的slot函数会在主线程中执行,而不是次线程。除非QThread对象依附到次线程中(通过movetoThread)。

或许你可能会感兴趣:

QT 多线程 之MoveToThread使用详解

QT发送结构体信号 

二、信号

声明信号使用signals关键字,发送信号使用emit关键字。

注意点:

1.所有的信号声明都是公有的,所以Qt规定不能在signals前面加public,private, protected。

2.所有的信号都没有返回值,所以返回值都用void

3.所有的信号都不需要定义

4.必须直接或间接继承自QOBject类,并且开头私有声明包含Q_OBJECT

5.在同一个线程中,当一个信号被emit发出时,会立即执行其槽函数,等槽函数执行完毕后,才会执行emit后面的代码,如果一个信号链接了多个槽,那么会等所有的槽函数执行完毕后才执行后面的代码,槽函数的执行顺序是按照它们链接时的顺序执行的。不同线程中(即跨线程时),槽函数的执行顺序是随机的。

6.在链接信号和槽时,可以设置链接方式为:在发出信号后,不需要等待槽函数执行完,而是直接执行后面的代码,是通过connect的第5个参数。

7.信号与槽机制要求信号和槽的参数一致,所谓一致,是参数类型一致。如果不一致,允许的情况是,信号的参数可以比槽函数的参数多,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少),但是不能说信号根本没有这个数据,你就要在槽函数中使用(就是槽函数的参数比信号的多,这是不允许的)。

三、connect函数原型

a.如:connect(pushButton, SIGNAL(clicked()), dialog, SLOT(close()));Qt4和Qt5都可以使用这种连接方式。

    static QMetaObject::Connection connect(    const QObject *sender,    //信号发送对象指针    const char *signal,//信号函数字符串,使用SIGNAL()    const QObject *receiver,  //槽函数对象指针    const char *member,//槽函数字符串,使用SLOT()    Qt::ConnectionType = Qt::AutoConnection);

b.如:connect(pushButton, &QPushButton::clicked, dialog, &QDialog::close);这是Qt5新增的连接方式,这使得在编译期间就可以进行拼写检查,参数检查,类型检查,并且支持相容参数的兼容性转换。

    static QMetaObject::Connection connect(    const QObject *sender,      //信号发送对象指针    const QMetaMethod &signal,  //信号函数地址    const QObject *receiver,    //槽函数对象指针    const QMetaMethod &method,  //槽函数地址    Qt::ConnectionType type = Qt::AutoConnection);

四、信号与槽的多种用法

1、一个信号可以和多个槽相连;

2、多个信号可以连接到一个槽;

3、一个信号可以连接到另外的一个信号;

4、槽可以被取消链接.

其写法和connect一样,只需要将connect换成disconnect即可。

五、槽的属性

public slots:在这个区内声明的槽意味着所有对象都可将信号和之相连接。这对于组件编程非常有用,你能创建彼此互不了解的对象,将他们的信号和槽进行连接以便信息能够正确的传递。 
protected slots:在这个区内声明的槽意味着当前类及其子类能将信号和之相连接。
private slots:在这个区内声明的槽意味着只有类自己能将信号和之相连接。

注:信号和槽不能携带模板类参数.
补充:

Qt提供了一种机制,能够自动、有效的组织和管理继承自QObject的Qt对象,这种机制就是对象树.

优点:能够帮助程序员缓解内存泄露的问题,提高编程效率,同时也保证了系统的稳健性.

举例:当应用程序创建了一个具有父窗口部件的对象时,该对象将被加入父窗口部件的孩子列表。当应用程序销毁父窗口部件时,其下的孩子列表中的对象将被一一删除.这就是为什么我们创建出一个对象时,都最好在初始化的时候加上this指针.new了一个父窗口后,只要delete父窗口后,那它的子窗口都会被自动释放,释放顺序(即析构顺序)与这些子对象的构造顺序相反.