qt信号与槽详解_qt的信号槽跨线程程序崩溃

qt信号与槽详解_qt的信号槽跨线程程序崩溃注意:信号发送给信号容易阻塞,需要设置好QObject::Connect函数中第五个参数,Qt::DirectConnection:发送的信号在哪个线程则接收方就运行在哪个线程上

qt信号与槽详解_qt的信号槽跨线程程序崩溃

注意:信号发送给信号容易阻塞,需要设置好QObject::Connect函数中第五个参数,Qt::DirectConnection:发送的信号在哪个线程则接收方就运行在哪个线程上。

前言
信号槽是Qt引以为豪的机制之一。所谓信号槽,实际就是观察者模式。当某个事件发生后,比如,按钮检测到自己被点击后,会发出一个信号。这种发出是没有目的的,类似广播。如果对象对这个信号感兴趣,它就使用连接(connect)函数连接槽函数,即槽函数绑定这个信号,当信号发出时,被连接的槽函数会自动被回调。

信号和槽实现原理
利用元对象系统实现,Qt的元对象系统预处理器叫做moc,对文件预处理之后生成一个moc_xxx.cpp文件,然后和其他文件一块编译即可。
详情Qt信号与槽实现原理

一、信号和槽连接方式

1、信号和槽用connect连接,其函数为

    static bool connect(const QObject *sender, const QMetaMethod &signal,
                        const QObject *receiver, const QMetaMethod &method,
                        Qt::ConnectionType type = 
#ifdef qdoc
                        Qt::AutoConnection
#else
#ifdef QT3_SUPPORT
                        Qt::AutoCompatConnection
#else
                        Qt::AutoConnection
#endif
#endif
        );

connect(①信号发送者,②信号,③接收者,④槽函数,⑤连接类型); 通常我们使用很少会填第五个参数,一般都是默认的连接类型

AutoConnection/Qt::AutoCompatConnection

2、在使用时有以下几种格式:

/*这里直接以类名Widget中按钮点击信号为例*/

① connect(this,SIGNAL(clicked(bool)),this,SLOT(dealclicked()));

② connect(this,&Widget::clicked,this,&Widget::dealclicked);

③ connect(this,&Widget::clicked,this,[=](){

        /*直接执行相关操作*/
   });

/*注:建议使用方法①,其优点,参数直观;缺点,类型不做检测(编译不做检测,运行报错)

 方法③是Qt5中lambda表达式*/

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

Qt::DirectConnection:槽函数会在信号发送的时候直接被调用,槽函数运行于信号发送者所在线程。效果看上去就像是直接在信号发送位置调用了槽函数。这个在多线程环境下比较危险,可能会造成奔溃。

Qt::QueuedConnection:槽函数在控制回到接收者所在线程的事件循环时被调用,槽函数运行于信号接收者所在线程。发送信号之后,槽函数不会立刻被调用,等到接收者的当前函数执行完,进入事件循环之后,槽函数才会被调用。多线程环境下一般用这个。

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

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

Qt::AutoCompatConnection:是为了连接Qt4与Qt3的信号槽机制兼容方式,工作方式与Qt::AutoConnection一样。

三、信号和槽的使用
1、信号可以连接信号,例如:

      connect(ui->pushButton,SIGNAL(clicked(bool)),ui->pushButton_2,SIGNAL(clicked(bool)));
1
2、信号可以连接槽,一个信号可以连接多个槽,槽的调用顺序是不确定的

3、多个信号可以连接同一个槽

4、信号与槽都可以被重载、重载后使用6中的第一种方式连接要好一些,因为第一种连接方式能带上参数,例如:

     connect(this,SIGNAL(send(QString)),this,SLOT(dealsend(QString)));
     
     connect(this,SIGNAL(send()),this,SLOT(dealsend()));

5、信号和槽函数的参数必须一一对应,信号参数个数可以多余槽的参数个数,但类型要一一对应,例如:

     connect(ui->pushButton_2,SIGNAL(clicked(bool)),this,SLOT(dealclicked_2())); /*这样是可以的*/
     
     connect(ui->pushButton_2,SIGNAL(clicked(bool)),this,SLOT(dealclicked_2(QString))); /*这样是没用的*/

如果要断开信号和槽:
disconnect(this,SIGNAL(),this,SLOT());

disconnect(this,&Widget::signal,this,&Widget::slot);

四、使用注意

1、继承自QObject类,必须声明Q_OBJECT宏

2、声明信号signals、Q_SIGNALS,必须为void型,即: void xxx() 或 void xxx(参数类型1,参数类型2…),

发送信号为emit xxx(参数1,参数2…)。信号与槽不能有缺省参数,如void signal(int x=1) ,错误使用。

3、信号和槽函数参数类型必须对应,若信号的参数个数多于槽函数,多余的将被舍弃,若信号的参数少于槽函数则会报错。

4、声明槽slots、Q_SLOTS,槽有private、public、protected区分,槽相当于成员函数,可以直接调用

槽可以重载。

5、宏定义不能放在信号和槽中

6、函数指针不能作为信号和槽参数
 

今天的文章qt信号与槽详解_qt的信号槽跨线程程序崩溃分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/85153.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注