开发者

Qt force QCheckBox to emit signal on setChecked

If I called QCheckBox::se开发者_Python百科tChecked( x ) the toggled signal is only emitted if x is not the same as the current checkbox state. I understand the logic behind this, to avoid signaling if nothing has changed. However, in some situations where I have a more complicated widgets setup, I need the signal to always be emitted. This ensures anybody who has connected to the checkbox will receive the first state.

Is there a way to have QCheckBox::setChecked(bool) emit a signal regardless of whether the state has changed?


My simple workaround now is to just force the checkbox into multiple states by doing setChecked(!x) and setChecked(x). I was hoping for a more correct way of doing this.


Looking into the QAbstractButton implementation, 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 and emits a stateChanged() signal only if the state changed. I haven't tested this, but I think d->blockRefresh is set to false if you call QCheckBox::setChecked( ... ) directly.

If this is the case, it means you could subclass QCheckBox and override the checkStateSet() method to something like this:

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 must be initialised to Qt::Unchecked in the constructor.


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

If you can be 100% sure that your signals and slots are connected before the checkbox has a chance to change its state, every connected class can initialize itself safely assuming the checkbox is not checked. This is because checkboxes are always unchecked upon construction. This way you might not have to call setChecked() after connecting the signals.

However, This approach does not work if there is a chance a signal gets connected after the checkbox has already changed. I'm not 100% fond of this approach myself but it might be an option for you nevertheless.


One way would be to subclass QCheckBox and implement the emitting of signals in that 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 whenever the check state is set.


You could emit the signal with the current state yourself:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜