Qt如何阻碍信号的触发

简述

在之前的文章中我们使用connect来连接信号与槽函数,使用disconnec来断开信号与槽函数的连接。
今天介绍的方法是如何阻碍当前对象的信号触发,有两种方法,下面一一道来。

1、blockSignals() / signalsBlocked

阻碍当前对象的信号触发效果
bool QObject::blockSignals(bool block)
If block is true, signals emitted by this object are blocked (i.e., emitting a signal will not invoke anything connected to it). If block is false, no such blocking will occur.
The return value is the previous value of signalsBlocked().

获取当前对象的信号是否被阻碍
bool QObject::signalsBlocked() const
Returns true if signals are blocked; otherwise returns false.
Signals are not blocked by default.

如下方调用 m_wgtA->blockSignals(true); 则对象m_wgtA所有的信号被触发不会用任何作用(信号对应的槽函数不会被调用)。
下方代码中先获取到当前对象是否被阻碍,返回false,说明该对象的信号没有被阻碍,然后第一次调用blockSignals,返回值为false,这里为啥返回值还是为false,因为blockSignals的返回值是signalsBlocked方法的上一个值,在调用blockSignals之前,信号未被阻碍传递,所以第一次调用返回为false,而第二次调用则返回true。

class MyWgtA : public QWidget
{
	Q_OBJECT

public:
	MyWgtA(QWidget *parent = nullptr);

	void signalM(int);

signals:
	void signalA(double paramA);
};


class MyWgtB : public QWidget
{
	Q_OBJECT

public:
	MyWgtB(QWidget *parent = nullptr);

public slots:
	void onSlotB(double paramA);
};

void test()
{
	m_wgtA = new MyWgtA;
	m_wgtB = new MyWgtB;


    bool isBlocked = m_wgtA->signalsBlocked();          // 返回值:false;
    isBlocked = m_wgtA->blockSignals(true);             // 返回值:false;
	isBlocked = m_wgtA->blockSignals(true);             // 返回值:true;

    connect(m_wgtA, &MyWgtA::signalA, m_wgtB, &MyWgtB::onSlotB);
    
    // 因为调用了m_wgtA->blockSignals(true),所以该信号触发,对应的槽函数不会被调用;
	emit m_wgtA->signalA(12.21);
}

2、QSignalBlocker

QSignalBlocker(QObject *object)

QSignalBlocker是Qt提供的一个类,主要是在他的构造函数中阻碍当前传入object对象信号的传递,在析构函数中解除阻碍效果

我们看到下面的代码中,其实QSignalBlocker类的作用是跟blockSignals方法类似的,都是阻碍当前对象的信号传递。

QObject * object = new QObject();

const QSignalBlocker blocker(someQObject);
// 等同于
const bool wasBlocked = someQObject->blockSignals(true);

3、不同点

但这两种方式实际上有不同的用法:
blockSignals这种方式是通过对象本身来调用,阻碍信号的传递,可随时调用,随时取消,但是如果调用参数为true,该对象的信号触发就一直没有任何作用,除非再次调用参数为false。

QSignalBlocker类是在构造中阻碍对象信号的传递,而在析构中解除这种效果,所以此方式也不一定需要手动解除,在适当的生命周期内会自动解除。如下方代码中,我们在test方法中传入对象object,然后使用QSignalBlocker类阻碍object对象的信号传递,当test方法结束之后会自动解除object对象的信号传递,因为QSignalBlocker类的生命周期只存在于test方法中,出了这个方法这个类就已经被析构了,所有也就自动解除了。
所有如果我们需要一个对象的信号在某些情况下(一段时间内)不被触发,我们可以使用这种方式,我们不需要去关心何时来解除信号被阻塞传递,我们只需要在这个test方法中(test方法的生命周期内)把需要做的事情做完即可。

同时QSignalBlocker类也提供了unblock()方法和reblock()方法用于解除阻碍和重新阻碍信号的传递。

void QSignalBlocker::reblock()
void QSignalBlocker::unblock()

void test(QObject * object)
{
    // 阻碍object对象的信号传递;
    const QSignalBlocker blocker(object);
    // todo;
    ...
    
    // 出了此方法之后,信号即可正常传递;
}

综上,blockSignals方式比较灵活,通过对象本身随调随用,而QSignalBlocker类需要创建对象,但是由于对象生命周期的缘由,在析构中会自动解除阻碍效果,不同方法适合不同的应用场景,具体怎么用就看小伙伴的使用场景了。

但是需要注意的是是 QObject类的destroyed()信号,此信号在对象被销毁前会发出,且不会被阻碍传递。

[signal] void QObject::destroyed(QObject *obj = nullptr)
This signal is emitted immediately before the object obj is destroyed, and can not be blocked.
All the objects’s children are destroyed immediately after this signal is emitted.


Qt训练营内容(一期)开始啦 ,更多详细的文章有兴趣的小伙伴可以点击看一看哈,里面有更多优质的内容等着你!也可以加群 861353824一起交流哈!

你可能感兴趣的:(Qt,Qt基础常识详解,qt,connect,信号槽,信号的阻断,signal)