信号与槽是如何实现的_使用信号槽通信

我们都知道信号槽.

但很多同学不知道怎么用它在Qt里实现类与类通信.

首先要搞清楚,Qt类与类之间通信有2种情况:

(1) 两个类之间没有父子关系;

(2) 两个类之间有父子关系;

这篇文章讲的是有父子关系的2个类使用信号槽通信.

当然,没有父子关系的也能用信号槽通信,但是必须要有一个设计成单例模式.

Qt单例模式

假设有2个类: Father和Son.

它们有父子关系,其中Father包含了Son.

那么Father如何发送数据给Son或者Son如何发送数据给Father呢?

 1   Father发送数据给Son

父发给子这个很简单,就算不使用信号槽也可以实现.

例如Father想发"helloworld"给Son,就可以:

(1) 在Son里定义一个函数setData(QString data);

(2) Father里调用son->setDate("helloworld");即可;

.h如下:

class Son {public:    explicit Son();    void setData(QString data);private:    QString buf;};class Father {public:    explicit Father();    Son *s;};

.cpp如下:

Son::Son(){}void Son::setData(QString data){    buf = data;    qDebug() << buf;}Father::Father(){    s = new Son();    s->setData("helloworld");}

输出结果:

0b4d2b0f8aa9bf29f54ab79f6f47b363.png

我们可以看大,Father里的helloworld确实设到了Son里.

fe2190440a55b2b7a3e27df176279500.png

使用信号槽传的方法如下:

(1) 在父类里定义一个信号void signDataOk(QString data);

(2) 在子类写一个槽函数: void slotGetData(QString d);

(3) 注意信号和槽函数形参必须一模一样;

(4) 在父类里关联信号槽.当信号发出时就会触发子类槽函数,在子类槽函数的形参中即可获取数据.

.h代码:

//因为使用到信号槽,所以必须继承QObject和在类里定义Q_OBJECT宏class Son : public QObject {    Q_OBJECTpublic:    explicit Son();    void setData(QString data);private:    QString buf;private slots:    void slotGetData(QString d);};class Father : public QObject{    Q_OBJECTpublic:    explicit Father();    Son *s;signals:    void signDataOk(QString data);};

.cpp代码:

Son::Son(){}void Son::slotGetData(QString d){    qDebug() << "recv=" + d;}void Son::setData(QString data){    buf = data;    qDebug() << buf;}Father::Father(){    s = new Son();    //手动关联信号槽    connect(this, SIGNAL(signDataOk(QString)), s, SLOT(slotGetData(QString)));    //发射信号,会触发Son的槽函数    emit signDataOk("hello world");}
 2   Son发数据给Father

Father发送数据给Son其实很简单,因为在Father里可以轻松的获取到Son的对象指针.

但是反过来就不行了,因为在Son里很难获取到Father的指针,而且Qt官方也不推荐这样做,因为"子对象获取父对象的指针会很危险".

那么这个时候Son想发数据给Father必须得使用信号槽了.

其实方法和之前说的差不多,也是定义信号,然后关联信号槽.

由于非常像,直接放代码了:

.h文件:

//因为使用到信号槽,所以必须继承QObject和在类里定义Q_OBJECT宏class Son : public QObject {    Q_OBJECTpublic:    explicit Son();private:    QString buf;    QTimer *timer;signals:    void signDataOk(QString data);private slots:    void slotTimeOut();};class Father : public QObject{    Q_OBJECTpublic:    explicit Father();    Son *s;private slots:    void slotGetData(QString d);};

.cpp文件:

Son::Son(){    timer = new QTimer(this);    connect(timer, SIGNAL(timeout()), this, SLOT(slotTimeOut()));    timer->start(1000); //每隔一秒发送一次}void Son::slotTimeOut(){    //发射信号,会触发Son的槽函数    emit signDataOk(QString("hello world"));}Father::Father(){    s = new Son();    //手动关联信号槽    connect(s, SIGNAL(signDataOk(QString)), this, SLOT(slotGetData(QString)));}void Father::slotGetData(QString d){    qDebug() << "recv=" + d;}

运行结果:

51e677a1af0e1d1f3393a84d649a40b7.png

后记

子通过信号槽发送数据给父对象这种框架是很常见的.

例如摄像头监控界面.

我们知道主界面里是不能死循环的,在主界面里死循环直接界面卡死,不信你试试.

所以必须要用子线程来循环接收图像,然后通过信号发送给主界面显示.

这种框架的共同点:

父界面显示数据,子线程死循环接收数据发送给父界面.

做Qt项目,假如功能包括串口,CAN,485通信等等,都可以使用这种框架来设计.

☆ END ☆

关注梅老师

学习嵌入式

梅老师

3a6a760988e4b8930e6822c730d15a04.png
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值