Reputation: 12273
I have a combo which is disabled, but adding an element to it will emit the currentIndexChanged(int)
signal.
I expected signals to be naturally turned off when a widget is disabled, but it's not the case. I know there is blockSignals(bool)
, but if there are many widgets whose signals must be "blocked when disabled", blockSignals
would require a Boolean state for each widget.
How can I disable the signals sent by a widget when it is disabled (and not alter its blockSignals
state)?
EDIT
To clarify: since this is a widget, user cannot interact with it when it's disabled, but some signals are emitted when altering the widget programmatically. In my case there are two interesting signals:
currentIndexChanged(int)
and activated(int)
The problem in my code is that I sometimes alter the combo programmatically AND I wish it to emit a signal, and sometimes it's the user that alters the combo by interacting. That's why I am using currentIndexChanged
and not activated
.
In both cases, anyway, I don't want the signals to be emitted when widget is disabled.
Upvotes: 2
Views: 3550
Reputation: 98425
In your case, the signals are the sole source of state information carried on to other objects. If you disable them, the other objects won't ever get any notification that the state was changed. This can cause bugs in the objects that depend on being informed of your widget's state.
There are at least two solutions:
Don't change the widget's state. You can certainly defer the update of the widget's contents until after it gets reenabled.
Create a proxy that monitors the originating widget's state, and queues up the signals (with compression) until the widget gets reenabled.
Due to those workarounds, your design may require a rework. Perhaps it'd be better if you could cope with signals from those disabled widgets. You should also evaluate whether disabling a widget doesn't break the user experience. What if the user wants to see the contents of a widget, but doesn't mean to change the current setting? A disabled widget in such a case is going too far. You can make you own, perhaps subclassed, widget, acting so that the control is not disabled, but the current element stays fixed. This could even be a separate object, applicable to any control - through judicious leverage of the user property.
Upvotes: 0
Reputation: 53155
The QComboBox
signals are user interaction based from end user point of view if you only have a QComboBox
and nothing else as your question seems to imply.
I simply cannot reproduce the issue. I have just made a short program where I cannot get any of the QComboBox signals emitted since I cannot simply interact with the widget.
Edit: It might be a good idea to upate your question with more context for the casual readers, but based on further clarification in comments, yes, programatically it might be the case, but then signals might be useful to process programmatically, too, with corresponding slots, so it is not a major improvement if Qt blocks them automatically.
Luckily, the feature you wish to have is already available:
bool QObject::blockSignals(bool block)
If block is true, signals emitted by this object are blocked (i.e., emitting a signal will not invoke anything connected to it). If block is false, no such blocking will occur.
The return value is the previous value of signalsBlocked().
Note that the destroyed() signal will be emitted even if the signals for this object have been blocked.
If you want to do it for many widgets, create a simple function that you call instead of myWidget->setDisabled(true);
:
inline bool disableAndBlockSignals(QWidget *widget)
{
widget->setDisabled(true);
return widget->blockSignals(true);
}
If you want to disable only some of them, say, currentIndexChanged
, you can use disconnect manually then.
Upvotes: 2
Reputation: 4180
You can disconnect signals with the QObject::disconnect();
when you want to block them and then reconnecting them when you want to unblock them.
Upvotes: 1