9

Do I miss something or there is really no (ready / built-in) way to programmatically change the state of a QCheckBox without emitting the "void stateChanged ( int state )" signal?

The above-mentioned signal is emitted regardless of whether "void setCheckState ( Qt::CheckState state )" was called or the user changed the state via the ui, and there is no "stateEdited" signal like with the QLineEdit.

So, if there is no ready way to differentiate between programmatic and user-induced changes to the state of the QCheckBox, and the only options are subclassing / adding the "stateEdited" signal or fiddling with "void QObject::blockSignals( bool block )", why does this have to be so, i.e., is it an (some sort of) inconsistency (in Qt)?

mlvljr
  • 4,066
  • 8
  • 44
  • 61

3 Answers3

16

If you only need to be informed of user input, listen to

QAbstractButton::clicked( bool checked );

Otherwise connect to

QAbstractButton::toggled( bool checked );

or

QCheckBox::stateChanged( int state);
TimW
  • 8,351
  • 1
  • 29
  • 33
9

An approach that works for all signals and widgets is to wrap the calls to setChecked() in a pair of blockSignals() calls:

const bool blocked = but->signalsBlocked();
but->blockSignals( true );
but->setChecked( true );
but->blockSignals( blocked );

or, with something every Qt programmer will have in his toolbox:

class QSignalBlocker {
    QObject * const o;
    const bool blocked;
public:
    explicit QSignalBlocker( QObject * o )
      : o( o ),
        blocked( o && o->signalsBlocked() )
    {
        if ( o ) o->blockSignals( true );
    }
    ~QSignalBlocker() { if ( o ) o->blockSignals( blocked ); }
};

a RAII class. Usage:

const QSignalBlocker blocker( but );
but->setChecked( true );

EDIT 2013-12-10: Qt 5.3 will have QSignalBlocker built-in.

Marc Mutz - mmutz
  • 24,485
  • 12
  • 80
  • 90
1

If you want to

programatically change the state of a QCheckBox

use setCheckState method.

P.S. I do not understand what does it mean

change the state of a QCheckBox ... emitting a "void stateChanged ( int state )" signal

Probably you should read Signals and Slots topic more carefully.

Wildcat
  • 8,701
  • 6
  • 42
  • 63
  • It means that my english is BAD:) and also the following: 1) you call setCheckState(...) 2) "void stateChanged ( int state )" is not emitted. In other words, I'm interested in behaviour like that of QLineEdit. Quoting Qt documentation: "void QLineEdit::textEdited ( const QString & text ) [signal] ... Unlike textChanged(), this signal is not emitted when the text is changed programmatically, for example, by calling setText()." – mlvljr Dec 06 '09 at 21:49
  • I get your point. I see only one option: create and use instead of QCheckBox class your own class which is based on QCheckBox (subclass it) and then define new method (or redifine setChecked). Your method should differ from one of QCheckBox (http://qt.gitorious.org/qt/qt/blobs/master/src/gui/widgets/qcheckbox.cpp) only in the last line of code. You don't need emit stateChanged(state); But I don't think it's good solution... Why do you need such different behavior? – Wildcat Dec 06 '09 at 22:20
  • There seems to be a need to set up some widgets whose signals are already connected without emitting them (signals). Anyway, I can always use "QObject::blockSignals( bool block )". P.S. (off.) Your web page at is in Russian, are you really from there? – mlvljr Dec 06 '09 at 22:46
  • Aha! blockSignals seems to be a solution. So you found it by yourself. =) P.S. Yes, I'm Russian by origin. – Wildcat Dec 06 '09 at 23:05
  • Actually I kinda new it beforehand, just was wondering if there was an elegant possibility buried somewhere up the inheritance tree :) Thanks, в любом случае. – mlvljr Dec 06 '09 at 23:15