Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QStyle::drawControl() not correctly painting enabled/disabled state
Forum Updated to NodeBB v4.3 + New Features

QStyle::drawControl() not correctly painting enabled/disabled state

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 3 Posters 198 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    peter.thompson
    wrote last edited by
    #1

    I have a custom delegate that is subclassed from QStyledItemDelegate. In the paint() method for this delegate, I'm using QStyle::drawControl() to draw a check box in the current application's style. I would like to have this check box appear disabled (i.e. grayed out) if the current index is uneditable. However, I can't figure out how to get this to work.

    Here is what I have currently:

    void MyCheckBoxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
    {
        this->QStyledItemDelegate::paint(painter, option, index);
    
        QStyleOptionButton buttonOption;
        buttonOption.rect = MyCheckBoxDelegate::getCheckBoxRectangle(option);
    
        buttonOption.palette = option.palette;
        buttonOption.direction = option.direction;
        buttonOption.fontMetrics = option.fontMetrics;
        buttonOption.styleObject = option.styleObject;
    
        buttonOption.state = QStyle::State_None;
        buttonOption.state |= index.data().toBool() ? QStyle::State_On : QStyle::State_Off;
        if (index.flags().testFlag(Qt::ItemIsEditable))
            buttonOption.state |= QStyle::State_Enabled;
    
        QApplication::style()->drawControl(QStyle::CE_CheckBox, &buttonOption, painter, option.widget);
    }
    

    Right now, the check box always appears to be enabled. For reference, here's a comparison with an actual check box widget in the application:

    Enabled, On Enabled, Off Disabled, On Disabled, Off
    Widget 2d8d83e8-01c2-4437-883e-3812d76c5877-image.png 77e33711-629c-427c-bb63-2a1b2091f108-image.png 2cccc46c-51e4-4ed4-ae3f-9243ff144344-image.png 78015518-5ece-458d-ab5d-66320afc82a3-image.png
    Delegate 9d70b01a-1389-4fbb-9152-35111500c7b6-image.png cf3122e2-0d80-4a74-b0d5-7702841221ba-image.png 7f587661-0765-4341-bc59-72a14b5ecccf-image.png eebff7d1-0a45-4f90-a820-ad10b9c86657-image.png

    Am I doing something wrong? Or does QStyle->drawControl() not consider the enabled state when drawing?

    1 Reply Last reply
    0
    • P Offline
      P Offline
      peter.thompson
      wrote last edited by
      #4

      Some more information: I put a breakpoint on drawControl() and followed it through the Qt source code. The application style is a QWindows11Style, but it eventually gets down to QCommonStyle::drawControl(). There's a large switch statement, and it gets to this case for CE_CheckBox. I don't see anything directly in that code that compares the state with State_Enabled.

      That code then calls drawPrimitive() with PE_IndicatorCheckBox. That method also has a large switch statement, and it gets to this case for PE_IndicatorCheckBox. I don't see anything here that compares the state with State_Enabled.

      Going back up to the case in QCommonStyle::drawControl(), it next recursively calls itself with CE_CheckBoxLabel. That takes us to this case for CE_CheckBoxLabel. I'm only seeing that it compares with State_Enabled to adjust how the icon or text are displayed, but both are null/empty in my case.

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote last edited by
        #2

        Hi,

        Might be a silly question but did you check the value of state in each of these cases ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        P 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          Might be a silly question but did you check the value of state in each of these cases ?

          P Offline
          P Offline
          peter.thompson
          wrote last edited by peter.thompson
          #3

          @SGaist The incoming state for option is State_Enabled|State_Children|State_Sibling. The state on buttonOption is being set to State_On / State_Off when the index is not editable and set to State_On|State_Enabled / State_Off|State_Enabled when the index is editable.

          1 Reply Last reply
          0
          • P Offline
            P Offline
            peter.thompson
            wrote last edited by
            #4

            Some more information: I put a breakpoint on drawControl() and followed it through the Qt source code. The application style is a QWindows11Style, but it eventually gets down to QCommonStyle::drawControl(). There's a large switch statement, and it gets to this case for CE_CheckBox. I don't see anything directly in that code that compares the state with State_Enabled.

            That code then calls drawPrimitive() with PE_IndicatorCheckBox. That method also has a large switch statement, and it gets to this case for PE_IndicatorCheckBox. I don't see anything here that compares the state with State_Enabled.

            Going back up to the case in QCommonStyle::drawControl(), it next recursively calls itself with CE_CheckBoxLabel. That takes us to this case for CE_CheckBoxLabel. I'm only seeing that it compares with State_Enabled to adjust how the icon or text are displayed, but both are null/empty in my case.

            1 Reply Last reply
            0
            • P Offline
              P Offline
              peter.thompson
              wrote last edited by peter.thompson
              #5

              Turns out it was the palette. You have to set the "current color group" for the palette to QPalette::Disabled. In fact, setting the state doesn't seem to have any effect whatsoever. Setting the palette alone is enough to control the color (and make it appear disabled). But I think I'll keep setting the state just in case it has an effect in other styles.

              void MyCheckBoxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
              {
                  this->QStyledItemDelegate::paint(painter, option, index);
              
                  QStyleOptionButton buttonOption;
                  buttonOption.rect = MyCheckBoxDelegate::getCheckBoxRectangle(option);
              
                  buttonOption.palette = option.palette;
                  buttonOption.direction = option.direction;
                  buttonOption.fontMetrics = option.fontMetrics;
                  buttonOption.styleObject = option.styleObject;
              
                  buttonOption.state = QStyle::State_None;
                  buttonOption.state |= index.data().toBool() ? QStyle::State_On : QStyle::State_Off;
              
                  if (index.flags().testFlag(Qt::ItemIsEditable))
                  {
                      buttonOption.state |= QStyle::State_Enabled;
                      buttonOption.palette.setCurrentColorGroup(QPalette::Normal);
                  }
                  else
                  {
                      buttonOption.palette.setCurrentColorGroup(QPalette::Disabled);
                  }
              
                  QApplication::style()->drawControl(QStyle::CE_CheckBox, &buttonOption, painter, option.widget);
              }
              
              1 Reply Last reply
              0
              • P peter.thompson has marked this topic as solved
              • Christian EhrlicherC Offline
                Christian EhrlicherC Offline
                Christian Ehrlicher
                Lifetime Qt Champion
                wrote last edited by
                #6

                This problem is fixed with Qt6.10, maybe also with 6.9 but don't know exactly since there are a lot of changes in the windows11 style as it is not yet finished. This works fine for me with git HEAD:

                class Delegate : public QStyledItemDelegate
                {
                public:
                    using QStyledItemDelegate::QStyledItemDelegate;
                
                    void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
                    {
                        QStyleOptionButton buttonOption;
                        buttonOption.rect = option.rect;
                        buttonOption.palette = option.palette;
                        buttonOption.direction = option.direction;
                        buttonOption.fontMetrics = option.fontMetrics;
                        buttonOption.styleObject = option.styleObject;
                        buttonOption.state = QStyle::State_None;
                        buttonOption.state |= index.column() % 2 == 0 ? QStyle::State_On : QStyle::State_Off;
                        if (index.column() < 2)
                            buttonOption.state |= QStyle::State_Enabled;
                
                        option.widget->style()->drawControl(QStyle::CE_CheckBox, &buttonOption, painter, option.widget);
                    }
                };
                

                grafik.png

                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                Visit the Qt Academy at https://academy.qt.io/catalog

                1 Reply Last reply
                1

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved