QT跨线程连接信号和槽

对QT的信号和槽理解较为初级,今天通过多次尝试,终于学会了跨线程连接信号和槽。其基本方法如下。

1. 无参数传递时

(1)定义:

signal:

    void signal1();

(2)连接部分写法:

connect( p_class1,                   //类1的指针

               SIGNAL(signal1()), //类1的信号

               p_class2,                  // 类2的指针

               SLOT(slot_func2())); //类2的槽函数

(3)释放信号写法:

emit signal1();

2. 有参数传递时

(1)定义:

signal:

    void signal1(TYPE);

(2)连接部分写法:

connect( p_class1,                   //类1的指针

               SIGNAL(signal1(TYPE)), //类1的信号

               p_class2,                  // 类2的指针

               SLOT(slot_func2(TYPE))); //类2的槽函数

(3)释放信号写法:

emit signal1(type_example);

3.注意的问题

根据查阅网上资料,信号的参数和槽的参数必须符合以下两种情况之一:

(1)信号的参数和槽的参数数量相同、类型一一对应也相同。

(2)信号的参数多于槽的参数,但与槽的参数对应的信号中的参数类型应一一对应相同。

另外,QT5中关于信号和槽的绑定针对QT4有了较大改进,提供了一种新的绑定方式:

connect( p_class1,                   //类1的指针

               &CLASS1::signal1;    //类1的信号

               p_class2,                  // 类2的指针

               &CLASS2::func2;    //类2的函数

这两种方式的区别可在网上找到比较好的解释。在《QT5编程入门》(霍亚飞等编著)一书中,对QT5新提供方式的优点介绍如下:


### Qt 中使用信号进行跨线程通信 在 Qt 的多线程环境中,信号是一种强大的工具,能够实现线程间的高效通信。以下是关于如何利用信号完成跨线程通信的具体方法。 #### 1. 基础概念 信号机制支持多种类型的通信方式,包括同步异步模式[^2]。对于跨线程的情况,默认情况下采用的是 **Queued Connection** 或者 **Blocking Queued Connection**,这取决于连接的方式设置以及目标对象所在的线程。 当一个信号被发射时,其携带的参数会被封装成事件并加入到接收方所在线程的事件队列中。随后,该线程中的事件循环会依次处理这些事件并将它们分发至对应的函数[^2]。 #### 2. 实现步骤 下面是一个具体的例子展示如何通过信号实现在两个独立线程之间的数据传输: ##### 定义工作线程类 创建继承自 `QThread` 的子类或者直接在一个普通的 QObject 上启动新线程。 ```cpp class Worker : public QObject { Q_OBJECT public: explicit Worker(QObject *parent = nullptr); signals: void resultReady(const QString &result); public slots: void process(); }; ``` 在这个简单的 worker 类里定义了一个名为 `process()` 的公共用来执行耗时的任务,并且有一个叫做 `resultReady` 的信号用于通知主线程任务已完成的结果。 ##### 主窗口或控制中心部分 这里我们假设存在另一个负责显示结果的对象(例如 GUI 组件)。 ```cpp class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); private slots: void handleResults(const QString &results); }; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){ connect(&workerObject, &Worker::resultReady, this, &MainWindow::handleResults); } void MainWindow::handleResults(const QString &results) { ui->textEdit->append(results); // 显示接收到的信息 } ``` 上面代码片段设置了从 work 对象发出的 signal 到 main window 接收器 slot 的关联关系。 ##### 启动线程及初始化 最后一步就是实例化上述组件并让整个流程运转起来。 ```cpp int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow w; w.show(); Worker myWorker; QThread thread; myWorker.moveToThread(&thread); QObject::connect(&w.buttonStart, &QPushButton::clicked, [&]() {myWorker.process();}); QObject::connect(&thread,&QThread::started,[&]{myWorker.startWork();}); QObject::connect(&myWorker,SIGNAL(finished()),SLOT(quit())); QObject::connect(&myWorker,SIGNAL(finished()),this,SLOT(deleteLater())); thread.start(); return app.exec(); } ``` 此段程序展示了完整的生命周期管理——不仅包含了基本的功能逻辑还考虑到了资源释放等问题。 #### 3. 注意事项 - 如果需要在线程间传递较大的数据结构,则建议使用引用传参而非值拷贝以降低内存消耗[^3]。 - 需要特别注意线程安全性问题,在某些特殊场景下可能还需要额外加锁保护共享变量[^3]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值