Important: Please read the Qt Code of Conduct -

SetEnabled vs. setDisabled

  • I just had the problem that a widget was not disabled with @widget->setEnabled(false);@ but it works with @widget->setDisabled(true);@ . Can anyone explain please how that comes?


  • Lifetime Qt Champion


    Without any more information like Qt and OS version, it's pretty much impossible tell. Also are you using a custom widget ? Are you doing anything special with it ?

  • It is Qt 4.8.3 on Win7 in this case. Indeed it is a custom component which overrides setEnabled but just to keep track of its state more or less and then QWidget::setEnabled() is called.
    Because I am not doing anything special things I am curious about this behaviour.

  • Lifetime Qt Champion

    Does your component directly inherits from QWidget ?

  • Damn, I think I know the problem. This might get a little complicated now. ;)

    A is parent of B which is parent of C. B does not call QWidget::setEnabled in the overridden method but C does (my fault). Now I am disabling A (which disables all children). Then I do some stuff and enable A again but want B to still be disabled and therefore I call setEnabled(false) of B which does not work because apparently the disabled property is still set (even though the component is enabled) and the component will not be disabled again.

    Could that be a possible explanation?

  • Lifetime Qt Champion

    Could be yes, If you are toying with the enabled/disabled state of the children widget it can quickly get messy

  • I think your problem is a different one. As setEnabled and setDisabled are not virtual, you're not reimplementing them but hiding them.
    There is no separate disabled property. setDisabled is just a convenience slot to enable a signal with a boolean value to either enable or disable on true. Lets look at the implementation of setDisabled in QWidget for reference:

    Disables widget input events if \a disable is true; otherwise
    enables input events.

    See the \l enabled documentation for more information.
    \sa isEnabledTo(), QKeyEvent, QMouseEvent, changeEvent()

    void QWidget::setDisabled(bool disable)
    You see? All setDisabled does is call setEnabled. But, it does that on QWidget, not on your derived class, as setEnabled is not virtual.

    It is almost never a good idea to override non-virtual methods (or members) in a sub class. It usually doesn't do what you want it to do.

  • Lifetime Qt Champion

    +1 for Andre, I've misunderstood your last post. He's completely right.

    To handle such enable/disable chain you will need to use your own function e.g. "setWidgetEnabled" (please find a better name).

  • [quote author="SGaist" date="1391503569"]To handle such enable/disable chain you will need to use your own function e.g. "setWidgetEnabled" (please find a better name).[/quote]

    I'd go about it in a different way. Adding a new function that does what the existing function does and a little more, and then requiring to use that new function and never to touch the inherited one is not a good idea. There is no way to force that in all cases, so it can (and thus, by Murphy: will) break.

    Instead, why not reimplement QWidget::changeEvent() in your widget? There, you can listen for the QEvent::EnabledChanged event to come by, and do whatever you need to do based on that. Don't forget to call the base implementation of changeEvent, as your base class will certainly need it as well. From the documentation:
    [quote] If your widget needs to know when it becomes enabled or disabled, you can use the changeEvent() with type QEvent::EnabledChange.[/quote]

  • Lifetime Qt Champion

    Even better ! I've forgotten about that event.

  • I was talking about the Qt::WA_Disabled attribute (not property, sorry).
    However I got the point now what setEnabled does not work but setDisabled does. The virtual is also not the problem but my wrong implementation of setEnabled.

    Thanks Andre and SGaist for pointing that out for me.

Log in to reply