Prevent the inclusion of signals in Qt

We have a QCheckBox object, when the user checks it or removes the check, we want to call the function so that we connect our function to the stateChanged ( int state ) signal. On the other hand, according to some condition, we also change the state of the QCheckBox object inside the code, and this causes an unwanted signal.

Is there a way to prevent the signal from triggering under certain conditions?

+41
c ++ checkbox qt signals-slots
Aug 24 2018-10-10T00:
source share
8 answers

You can use the clicked signal because it is emitted only when the user really clicked on this flag, and not when you manually check it using setChecked .

If you just don’t want the signal to come out at one specific time, you can use QObject::blockSignals as follows:

 bool oldState = checkBox->blockSignals(true); checkBox->setChecked(true); checkBox->blockSignals(oldState); 

The disadvantage of this approach is that all signals will be blocked. But I think this does not really matter in the case of QCheckBox .

+66
Aug 24 '10 at 13:13
source share
β€” -

You can always block signal emission in QObjects using QObject::blockSignals() . Note that for things to be correct, you must remember the old state (returned from the function call) and restore it when you are done.

In my work, we prefer RAII for this kind of thing. A simple class for this might look like this:

 class SignalBlocker { public: SignalBlocker( QObject *obj ) : m_obj( obj ), m_old( obj->blockSignals( true ) ) { } ~SignalBlocker() { m_obj->blockSignals( m_old ); } private: QObject *m_obj; bool m_old; }; 

Edit : starting with Qt 5.3, see QSignalBlocker (h / t for HappyCactus in the comments)

+28
Aug 24 '10 at 13:26
source share

You can QObject::disconnect remove the corresponding connection to the signal slot and again QObject::connect are fulfilled ...

+11
Aug 24 '10 at 13:18
source share

During Qt training, I ran into this problem with a set of interconnected widgets that I wanted to update atomically. I liked @cjhuitt's solution, but it turned out that it goes even better with a little syntax sugar based on proxy objects . Here's the approach I used ...

First, I defined a class template for a proxy blocker object. Like Caleb, this blocks building signals, and then restores their former state upon destruction. However, it also overloads the -> operator to return a pointer to a locked object:

 template<class T> class Blocker { T *blocked; bool previous; public: Blocker(T *blocked) : blocked(blocked), previous(blocked->blockSignals(true)) {} ~Blocker() { blocked->blockSignals(previous); } T *operator->() { return blocked; } }; 

Then I defined a small template function to build and return a blocker:

 template<class T> inline Blocker<T> whileBlocking(T *blocked) { return Blocker<T>(blocked); } 

Combining all this, I would use it as follows:

 whileBlocking(checkBox)->setChecked(true); 

or

 whileBlocking(xyzzySpin)->setValue(50); 

This gives me all the benefits of RAII, with auto-paired locking and recovery around the method call, but I don't need to specify any shell or state flags. It is beautiful, easy and beautifully agile.

+10
Jun 22 '14 at 8:10
source share

In QObject derived classes, you can call blockSignals(bool) to prevent the object from emitting. For example:

 void customChangeState(bool checked) { blockSignals(true); ui->checkBox->setCheckState(Qt::Checked); // other work blockSignals(false); } 

The above method will change the check state without clicking, stateChanged or any other emitted signals.

+5
Aug 24 '10 at 13:26
source share

Qt5.3 has implemented the QSignalBlocker class, which does exactly what is needed to be safe for exceptions.

 if (something) { const QSignalBlocker blocker(someQObject); // no signals here } 
+2
Apr 17 '15 at 9:45
source share

Even in QT5, it is a little cumbersome when there are many / several things that need to be blocked. Several object versions are used here:

 class SignalBlocker { public: SignalBlocker(QObject *obj) { insert( QList<QObject*>()<<obj ); } SignalBlocker(QList<QObject*> objects) { insert(objects); } void insert(QList<QObject*> objects) { for (auto obj : objects) m_objs.insert(obj, obj->signalsBlocked()); blockAll(); } void blockAll() { for( auto m_obj : m_objs.keys() ) m_obj->blockSignals(true); } ~SignalBlocker() { for( auto m_obj : m_objs.keys() ) m_obj->blockSignals( m_objs[m_obj] ); } private: QMap<QObject*,bool> m_objs; }; 

using:

 void SomeType::myFunction() { SignalBlocker tmp( QList<QObject*>() << m_paramWidget->radioButton_View0 << m_paramWidget->radioButton_View1 << m_paramWidget->radioButton_View2 ); // Do more work, ... } 
0
Jul 13 '15 at 3:14
source share

If any user interface element does not respond to the user, you should disable it. To let the user know that this element does not accept input.

-one
Jun 26 '13 at 13:52
source share



All Articles