QT信号槽连接方式

我们最常用的connect()函数的原型之一如下:

QMetaObject::Connection QObject::connect(const QObject * sender, const char * signal, const QObject * receiver, const char *

method, Qt::ConnectionType type = Qt::AutoConnection)

最后的ConnectionType是一个缺省的参数,默认为自动连接方式,我们来看一下这个参数有哪些值:

1. AutoConnection

自动连接,默认值。

If the signal is emitted in the thread which the receiving object has affinity then the behavior is the same as the Direct Connection.

Otherwise, the behavior is the same as the Queued Connection.

如果信号的发送者和信号的接受者的对象同属一个线程,那个工作方式与直连方式相同;否则工作方式与排队方式相同。

2. Direct Connection

直接连接。

The slot is invoked immediately, when the signal is emitted. The slot is executed in the emitter's thread, which is not necessarily

the receiver's thread.

当信号发出后,相应的槽函数将立即被调用;

emit语句后的代码将在所有槽函数执行完毕后被执行,信号与槽函数关系类似于函数调用,同步执行

3. Queued Connection

排队方式连接。

The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.

当信号发出后,排队到信号队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,调用相应的槽函数。

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

此时信号被塞到信号队列里了,信号与槽函数关系类似于消息通信,异步执行。

4. Blocking Queued Connection

阻塞的排队方式。

The slot is invoked as for the Queued Connection, except the current thread blocks until the slot returns.

Using this type to connect objects in the same thread will cause deadlock.

插槽作为队列连接调用,除非当前线程阻塞,直到插槽返回。

使用此类型连接同一线程中的对象将导致死锁。

5. Unique Connection

The behavior is the same as the Auto Connection, but the connection is made only if it does not duplicate an existing connection. 

Be aware that using direct connections when the sender and receiver live in different threads is unsafe if an event loop is running

in the receiver's thread, for the same reason that calling any function on an object living in another thread is unsafe.

该行为与自动连接相同,但是只有在不复制现有连接的情况下才会进行连接。

请注意,如果事件循环在接收方的线程中运行,那么当发送方和接收方位于不同线程中时使用直接连接是不安全的,这与调用

于另一个线程中的对象上的任何函数都是不安全的道理是一样的。

    // Qt4连接方式,信号发送者,信号,信号接受者,处理函数
    QObject::connect(ui->pushButton,SIGNAL(clicked(bool)),this,SLOT(qT4_slot()));


    // Qt5的新方法,编译会有安全监测
    QObject::connect(ui->pushButton,&QPushButton::clicked,this,&Widget::qT5_slot);


    // Qt5 Lambda表达式,这里需要注意 Lambda表达式是C++ 11 的内容,所以,需要再Pro项目文件中加入 CONFIG += C++ 11
    QObject::connect(ui->pushButton,&QPushButton::clicked,[=](){qDebug()<<"lambda 表达式";});

 

### Qt 中信号与槽的连接方式Qt 的信号与槽机制中,`QObject::connect()` 函数用于建立信号和槽之间的联系。以下是几种常见的连接方式及其对应的示例。 #### 1. 使用传统语法进行连接 传统的 `QObject::connect()` 方法通过字符串形式指定信号和槽的名字。这种方式适用于较旧版本的 Qt 和某些特定场景。 ```cpp // 假设有一个 QPushButton 对象 button 和一个 QLineEdit 对象 lineEdit QPushButton *button = new QPushButton(); QLineEdit *lineEdit = new QLineEdit(); // 将按钮点击信号 connect 到编辑框清空操作 QObject::connect(button, SIGNAL(clicked()), lineEdit, SLOT(clear())); ``` 此方法依赖于宏定义的信号和槽名称,在编译时不会检查其有效性[^4]。 --- #### 2. 使用现代 C++ lambda 表达式进行连接 自 Qt 5 起支持使用 Lambda 表达式的现代化连接方式,这种方法提供了更强的类型安全性和灵活性。 ```cpp #include <QDebug> // 创建对象实例 QPushButton *button = new QPushButton(); QObject *object = new QObject(); // 使用 Lambda 表达式绑定信号到匿名函数 QObject::connect(button, &QPushButton::clicked, [=]() { qDebug() << "Button was clicked!"; }); // 绑定信号到成员函数 QObject::connect(button, &QPushButton::clicked, object, [object]() { object->doSomething(); // 假设有 doSomething 成员函数 }); ``` Lambda 方式允许开发者执行更复杂的逻辑而无需显式声明额外的槽函数[^3]。 --- #### 3. 不同线程间的信号与槽连接 当涉及多线程编程时,可以通过设置合适的连接类型实现线程间的安全通信。 ##### (a) **自动连接 (`Qt::AutoConnection`)** 这是默认的行为模式,由框架自行判断发送方和接收方是否处于同一线程并决定采用何种具体策略。 ```cpp // 默认情况下会尝试 Auto Connection QObject::connect(senderObject, &SenderClass::someSignal, receiverObject, &ReceiverClass::someSlot); ``` 如果两者位于不同线程,则实际效果相当于选择了 Queued Connection;否则为 Direct Connection[^1]。 ##### (b) **队列连接 (`Qt::QueuedConnection`)** 强制将信号放入目标线程的消息循环队列等待处理。 ```cpp // 明确指明要使用 Queue Connection 类型 QObject::connect(senderThreadObj, &MyEmitter::dataReady, workerThreadObj, &Worker::processData, Qt::QueuedConnection); ``` 这种类型的优点在于能够有效避免竞态条件等问题发生。 ##### (c) **直接连接 (`Qt::DirectConnection`)** 无论当前上下文如何都会立刻调用关联上的 Slot 处理程序。 ```cpp // 即使跨越线程也立即响应 QObject::connect(mainWindowBtn, &QPushButton::pressed, backgroundTaskRunner, &BackgroundTask::startWork, Qt::DirectConnection); ``` 需要注意的是在这种情形下可能会破坏预期顺序或者引发潜在的数据竞争风险。 --- ### 总结 上述展示了三种主要的 Signal-Slot 配置手段以及各自适用范围。无论是经典风格还是新型解决方案都各有千秋,应依据项目需求合理选用最恰当的形式完成任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

于大博

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值