简述
在之前的文章中我们使用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一起交流哈!