关于QObject::blockSignals和QSignalBlocker的一些记录

  1. 作用
    bool QObject::blockSignals(bool block)
    可锁定/解锁对象的信号。

  2. 使用
    常用于限制信号的发送, 一般加锁和解锁成对出现。 如

	ui->comboBox->blockSignals(true);
    ui->comboBox->setCurrentIndex(3);
    ui->comboBox->blockSignals(false);

因为如果不先锁定信号,直接调用setCurrentIndex,则会触发comboBox的currentIndexChanged信号。

  1. QT内部实现
    实质上是修改了一个标志位:blockSig
bool QObject::blockSignals(bool block) noexcept
{
    Q_D(QObject);
    bool previous = d->blockSig;
    d->blockSig = block;
    return previous;
}

在事件循环的时候,会判断此标志位:

template <bool callbacks_enabled>
void doActivate(QObject *sender, int signal_index, void **argv)
{
    QObjectPrivate *sp = QObjectPrivate::get(sender);

    if (sp->blockSig)
        return;
    ...
    发送信号
}
  1. 其他
    在函数的说明文档中提到:

Note that the destroyed() signal will be emitted even if the signals for this object have been blocked.

意为 即使此对象锁定了信号,也会发送destroyed() 信号。
查看源码可得知,在object析构函数中,会先去将上述标志位改为false,这样就不会拒绝信号的发送。

QObject::~QObject()
{
    Q_D(QObject);
    d->wasDeleted = true;
    d->blockSig = 0; // unblock signals so we always emit destroyed()

    QtSharedPointer::ExternalRefCountData *sharedRefcount = d->sharedRefcount.loadRelaxed();
    if (sharedRefcount) {
        if (sharedRefcount->strongref.loadRelaxed() > 0) {
            qWarning("QObject: shared QObject was deleted directly. The program is malformed and may crash.");
            // but continue deleting, it's too late to stop anyway
        }

        // indicate to all QWeakPointers that this QObject has now been deleted
        sharedRefcount->strongref.storeRelaxed(0);
        if (!sharedRefcount->weakref.deref())
            delete sharedRefcount;
    }

    if (!d->isWidget && d->isSignalConnected(0)) {
        emit destroyed(this);
    }
    ...
}
  1. 关于QSignalBlocker
    使用QSignalBlocker类可替代blockSignals函数,防止锁定之后忘记解锁导致没有信号发出。
    QSignalBlocker内部实现了构造时加锁,析构时解锁(RAII思想)
QSignalBlocker::QSignalBlocker(QObject *o) noexcept
    : m_o(o),
      m_blocked(o && o->blockSignals(true)),
      m_inhibited(false)
{}

QSignalBlocker::~QSignalBlocker()
{
    if (m_o && !m_inhibited)
        m_o->blockSignals(m_blocked);
}

从源码中得知,其内部仍然调用的是blockSignals。

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值