Qt forces the QCheckBox to emit a signal to setChecked

If I called QCheckBox::setChecked( x ) , the toggled signal is only output if x does not match the current status of the flag. I understand the logic of this to avoid signaling if nothing has changed. However, in some situations, when I have a more complicated widget setup, I need a signal that always emits. This ensures that anyone who connects to the checkbox gets the first state.

Is there any way that QCheckBox::setChecked(bool) emits a signal regardless of whether the state has changed?


My simple solution now is to simply set the checkbox to multiple states by doing setChecked(!x) and setChecked(x) . I was hoping for a more correct way to do this.

+6
source share
4 answers

Looking at the implementation of QAbstractButton , I found the following lines of code:

 if (!d->checkable || d->checked == checked) { if (!d->blockRefresh) checkStateSet(); return; } 

where checkStateSet is a virtual function. QCheckBox overrides this value and emits the stateChanged() signal only if the state is changed. I have not tested this, but I think d->blockRefresh set to false if you call QCheckBox::setChecked( ... ) directly.

If so, that means you can subclass QCheckBox and override the checkStateSet() method as follows:

 void MyCheckBox::checkStateSet() { QCheckBox::checkStateSet(); if( m_oldState == checkState() ) { // emit the signal here, as QCheckBox::checkStateSet() didn't do it. emit stateChanged( m_oldState ); } else { // don't emit the signal as it has been emitted already, // but save the old state m_oldState = checkState(); } } 

where the header file contains

 private: Qt::CheckState m_oldState; 

which should be initialized in Qt::Unchecked in the constructor.

+6
source

Here is another solution that may or may not be possible for your case:

If you can be 100% sure that your signals and slots are connected before the flag has the ability to change its state, each connected class can safely initialize if the flag is not checked. This is due to the fact that the checkboxes are not always set during construction. This way you do not have to call setChecked() after connecting the signals.

However, this approach does not work if there is a chance that the signal will be connected after the flag has already changed. I do not really like this approach 100%, but it may be for you nonetheless.

+2
source

One way is to subclass QCheckBox and realize the emission of signals in the place where you need it, for example:

 class MyCheckBox : public QCheckBox { Q_OBJECT public: MyCheckBox(QWidget *parent = 0) : QCheckBox(parent) {}; virtual void setChecked(bool checked) { QCheckBox::setChecked(checked); emit checkWasSet(checked); }; signals: void checkWasSet(bool value); }; 

Now use this class instead of the regular QCheckBox class, and you can connect to the checkWasSet () signal for any validation state.

0
source

You can emit a signal with the current state yourself:

 checkbox.stateChanged.emit(checkbox.checkState()) 
0
source

Source: https://habr.com/ru/post/896327/


All Articles