QT的signal和slot的几种常见使用场景

原创 2016年03月03日 23:34:17

signal和slot是QT的经典应用。本文就signal和slot的几种常用场景做一简单介绍。


首先,先看2个类A和B的定义。

a.h如下:

#ifndef A_H
#define A_H

#include <QObject>

class A : public QObject
{
    Q_OBJECT
public:
    void emitSignalA() {
        signalA();
    }

signals:
    void signalA();
};

#endif // A_H

b.h如下:

#ifndef B_H
#define B_H

#include <QDebug>
#include <QObject>

class B : public QObject
{
    Q_OBJECT
public slots:
    void slotB() {
        qDebug()<<"slotB() is called.";
    }
};

#endif // B_H

三个常用场景都使用这2个类,但main.cpp不同。

场景一、A和B都在主线程中,且signal也在主线程中emit,那么B在主线程中执行slot,所以这是同步的。

1.cpp如下:

#include <QCoreApplication>
#include "a.h"
#include "b.h"

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    A a;
    B b;
    QObject::connect(&a,SIGNAL(signalA()),&b,SLOT(slotB()));

    a.emitSignalA();

    return app.exec();
}


场景二、A生在子线程中,B生在主线程中,A在子线程中emit signal,而B在主线程中执行slot,所以这是异步的。

#include <QCoreApplication>
#include <QThread>
#include "a.h"
#include "b.h"

B * g_pB = NULL;

class T : public QThread
{
public:
    void run() {
        A a;
        connect(&a,SIGNAL(signalA()),g_pB,SLOT(slotB()));
        a.emitSignalA();
        exec();
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    B b;
    g_pB = &b;
    T t;
    t.start();

    return app.exec();
}

场景三、A、B都出生在主线程中,而A在子线程中emit signal,B在主线程中执行slot,所以这还是异步的。

#include <QCoreApplication>
#include <QThread>
#include "a.h"
#include "b.h"

A * g_pA = NULL;
B * g_pB = NULL;

class T : public QThread
{
public:
    void run() {
        connect(g_pA,SIGNAL(signalA()),g_pB,SLOT(slotB()));
        g_pA->emitSignalA();
        exec();
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    B b;
    g_pB = &b;
    A a;
    g_pA = &a;
    T t;
    t.start();

    return app.exec();
}

由上可见,对场景三,虽然A和B都是在主线程初始,但因为A在子线程emit signal,所以B仍会在主线程执行slot,仍然是异步的。


当然,以上这些都是因为connect()的最后一个参数连接类型的默认值是AutoConnection。其详细解释可见:http://doc.qt.io/qt-5/threads-qobject.html ,本人译文在:http://blog.csdn.net/nirendao/article/details/50642701 . 摘要如下:

Qt支持如下的signal-slot连接类型:

  • Auto Connection(默认) :如果发射signal和接收的对象在同一个线程,那么行为等同于Direct Connection;否则,行为等同于Queued Connection. 
  • Direct Connection:当signal被发射后,slot立即被调用。slot在signal发射者所在的线程中被执行,而未必需要在接收者的线程中。
  • Queued Connection:当控制回到接收者的event loop后,slot才被调用。slot被执行在接收者的线程中。
  • Blocking Queued Connection:slot的调用情形和Queued Connection相同,不同的是当前的线程会阻塞住,直到slot执行结束返回。注意,在同一个线程中使用这种类型进行连接会导致死锁。
  • Unique Connection:行为与Auto Connection相同,但是连接只会在“不会与已存在的连接相同”时建立,即:如果相同的signal已经被连接到相同的slot,那么连接就不会被再次建立,而connect()函数会返回false. 

通过传递一个参数给connect()函数来指定连接类型。要知道的是,如果event loop运行在接收者的线程中,而sender和receiver在不同的线程时,使用Direct Connection是不安全的。同样的原因,调用存在于另一个线程中的对象的函数是不安全的。



版权声明:本文为博主原创文章,可以转载但必须注明出处。

相关文章推荐

Qt的signal和slot使用心得

1、connect指定的SIGNAL和SLOT的成员函数,不能携带参数名,只能带参数类型,比如:QObject::connect(pushButton, SIGNAL(clicked(bool)), ...

QT窗体间传值总结之Signal&Slot

在写程序时,难免会碰到多窗体之间进行传值的问题。依照自己的理解,我把多窗体传值的可以使用的方法归纳如下:       1.使用QT中的Signal&Slot机制进行传值;       2.使用全局...

Qt 定义信号 signals 和 槽 slots

1、signals前面不可加public、private和protected进行修饰;slots前面可以加,因为Qt说槽函数可以当普通函数使用。 2、signals区域的函数必须是void类型,...

Qt之信号signals和槽slots详解

目录(?)[-] 一概述 二信号 四信号和槽的关联 五元对象工具 六程式样例 七应注意的问题 8信号和槽也不能携带模板类参数 9嵌套的类不能位于信号或槽区域内也不能有信号或槽 10友元声明不能位...

Qt:信号与槽(Signals and Slots) 下

http://hi.baidu.com/spygg/item/519f4dd7575704ce1b72b4e7 信号(Signals) 只有定义了信号的类及其子类可以发出信号。   一个信号发...

Qt信号与槽机制(signal & slot)

QApplication 类管理图形用户界面应用程序的控制流和主要设置。 可以说QApplication是Qt的整个后台管理的命脉,它包含主事件循环,处理来自窗口系统和其它资源的所有事件。它也处理应用...

Qt的线程和 signal-slot

Qt事件和信号的区别 问题:     什么时候用事件,什么时候用信号呢?是不是不同的线程间用事件,信号不能用在线程间? 解答:     仔细来看,事件与信号其实并无多大差别...

Qt的Signal和Slot机制(二)

第二节 Signal和Slot的粘合剂 如果要连接一个Signal和Slot我们会用connect函数,下面我们就看一下connect是如何把Signal和Slot粘合在一起的。 以下是conn...

Qt中信号与槽机制中emit的应用

信号与槽机制是qt的核心,一个信号可以接多个槽,多个信号也可以接一个槽,当然一个信号也可以接一个槽。本文的重点是讲述emit的应用,emit是qt中定义的宏,是用来发送一个信号,然后你再写一个槽函数。...

Qt跨线程发送信号与元数据

Qt的signals/slots是可以用在线程间的。由于事件循环(event loop)是在主线程完成的,所以在非主线程发送一个信号时,对应的槽函数将会由主线程执行。 熟悉多线程的读者应该都感受到...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)