Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent Firing Signals in Qt

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

Is there any way to prevent firing signal under some conditions?

like image 279
metdos Avatar asked Aug 24 '10 13:08

metdos


People also ask

How do you block signals in Qt?

QSignalBlocker can be used wherever you would otherwise use a pair of calls to blockSignals(). It blocks signals in its constructor and in the destructor it resets the state to what it was before the constructor ran.

Can we define a private signal in Qt?

No. Signals cannot be public or private. Qt signals are protected class methods.

How do signals work in Qt?

Signals are emitted by an object when its internal state has changed in some way that might be interesting to the object's client or owner. Signals are public access functions and can be emitted from anywhere, but we recommend to only emit them from the class that defines the signal and its subclasses.

Are Qt signals asynchronous?

Signals are neither synchronous nor asynchronous. It's the slots that might be one of the two. Slots are by default synchronous when the object emitting the signal and the object having the receiving slot both live in the same thread.


2 Answers

You can use the clicked signal because it is only emitted when the user actually clicked the check box, not when you manually check it using setChecked.

If you just don't want the signal to be emitted at one specific time, you can use QObject::blockSignals like this:

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

The downside of this approach is that all signals will be blocked. But I guess that doesn't really matter in case of a QCheckBox.

like image 58
mtvec Avatar answered Oct 14 '22 12:10

mtvec


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

At my job, we prefer RAII for this sort of thing. A simple class to do so 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 to HappyCactus in comments)

like image 28
Caleb Huitt - cjhuitt Avatar answered Oct 14 '22 11:10

Caleb Huitt - cjhuitt