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. Qt6: Disable drawing of default background for QTreeView items
Forum Update on Monday, May 27th 2025

Qt6: Disable drawing of default background for QTreeView items

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 2 Posters 362 Views
  • 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.
  • kadet1090K Offline
    kadet1090K Offline
    kadet1090
    wrote on last edited by
    #1

    Prior to Qt 6.5 background for items was rendered only when alternating background for items was specified, allowing QStyledItemDelegate to render background independently. This however was changed by the qt/qtbase@16e0e7c commit. Another commit that is part of this regression: qt/qtbase@483ae6c. This one translates PanelItemViewRows into PanelItemViewItems to "properly" render background because it is non-styleable from qss.

    One solution would be to override PE_PanelItemViewRow using QProxyStyle but this does not work with stylesheets which is hard requirement as the app allows custom styling.

    Another possibility would be to set ::item in qss to have no background and somehow render it in QStyledItemDelegate but I don't know how to do it in a way that it would be possible to control it using qss. Maybe create artificial widget that will be the source for styles?

    Incorrect behavior:
    33680001-f973-4025-8015-6763e80a4b5a-image.png

    Expected one:
    393804fa-c6b0-42b6-ae84-d9efe800c48f-image.png

    M 1 Reply Last reply
    0
    • kadet1090K kadet1090

      Prior to Qt 6.5 background for items was rendered only when alternating background for items was specified, allowing QStyledItemDelegate to render background independently. This however was changed by the qt/qtbase@16e0e7c commit. Another commit that is part of this regression: qt/qtbase@483ae6c. This one translates PanelItemViewRows into PanelItemViewItems to "properly" render background because it is non-styleable from qss.

      One solution would be to override PE_PanelItemViewRow using QProxyStyle but this does not work with stylesheets which is hard requirement as the app allows custom styling.

      Another possibility would be to set ::item in qss to have no background and somehow render it in QStyledItemDelegate but I don't know how to do it in a way that it would be possible to control it using qss. Maybe create artificial widget that will be the source for styles?

      Incorrect behavior:
      33680001-f973-4025-8015-6763e80a4b5a-image.png

      Expected one:
      393804fa-c6b0-42b6-ae84-d9efe800c48f-image.png

      M Offline
      M Offline
      medyakovvit
      wrote on last edited by
      #2

      @kadet1090 I'm not sure if it's supported but try

      QTreeView::item:selected
      {
          background: transparent;
      }
      
      kadet1090K 1 Reply Last reply
      0
      • M medyakovvit

        @kadet1090 I'm not sure if it's supported but try

        QTreeView::item:selected
        {
            background: transparent;
        }
        
        kadet1090K Offline
        kadet1090K Offline
        kadet1090
        wrote on last edited by
        #3

        @medyakovvit This does not work as it disables background entirely for selected items which is not the goal.

        I managed to find a hacky solution to this problem.

        To disable rendering of the background I can abuse this if statement in Qt:

                // For compatibility reasons, QTreeView draws different parts of
                // the background of an item row separately, before calling the
                // delegate to draw the item. The row background of an item is
                // however not separately styleable through a style sheet, but
                // only indirectly through the background of the item. To get the
                // same background for all parts drawn by QTreeView, we have to
                // use the background rule for the item here.
                if (renderRule(w, opt, PseudoElement_ViewItem).hasBackground())
                    pseudoElement = PseudoElement_ViewItem;
        

        So disabling background for ::item disables rendering of branches and not-wanted background (I'm using qtsass):

          QTreeView::item {
            &, &:selected, &:hover {
              background: none;
              border: none;
            }
          }
        

        This however denies me from defining background in qss. But as a workarond I create artificial QTreeView widget inside the delegate with some well defined object name, DocumentTreeItems in my case:

        TreeWidgetItemDelegate::TreeWidgetItemDelegate(QObject* parent)
            : QStyledItemDelegate(parent)
        {
            artificial = new QTreeView(qobject_cast<QWidget*>(parent));
            artificial->setObjectName("DocumentTreeItems");
            artificial->setFixedSize(0, 0);
        }
        

        Thanks to that I can attach styles to this widget inside qss:

          #DocumentTreeItems::item {
            border: 1px solid transparent;
            border-radius: 2px;
            background-color: $primaryBackground;
        
            &:hover {
              border: 1px solid $contrastBorder;
              background-color: $controlWidgetBackground;
            }
        
            &:selected {
              border: 1px solid $accentBorder;
              background-color: $accentBackground;
            }
          }
        

        Then I can repaint the background using style and referring to my artificial widget in the paint method of delegate:

            style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, artificial);
        

        This gives the expected result:

        4704bbef-cb61-4bdd-9034-74854ca86f8f-image.png

        I'm however deeply dissatisfied with this solution, so if anyone knows a better one I'd be glad to hear suggestions.

        M 1 Reply Last reply
        0
        • kadet1090K kadet1090

          @medyakovvit This does not work as it disables background entirely for selected items which is not the goal.

          I managed to find a hacky solution to this problem.

          To disable rendering of the background I can abuse this if statement in Qt:

                  // For compatibility reasons, QTreeView draws different parts of
                  // the background of an item row separately, before calling the
                  // delegate to draw the item. The row background of an item is
                  // however not separately styleable through a style sheet, but
                  // only indirectly through the background of the item. To get the
                  // same background for all parts drawn by QTreeView, we have to
                  // use the background rule for the item here.
                  if (renderRule(w, opt, PseudoElement_ViewItem).hasBackground())
                      pseudoElement = PseudoElement_ViewItem;
          

          So disabling background for ::item disables rendering of branches and not-wanted background (I'm using qtsass):

            QTreeView::item {
              &, &:selected, &:hover {
                background: none;
                border: none;
              }
            }
          

          This however denies me from defining background in qss. But as a workarond I create artificial QTreeView widget inside the delegate with some well defined object name, DocumentTreeItems in my case:

          TreeWidgetItemDelegate::TreeWidgetItemDelegate(QObject* parent)
              : QStyledItemDelegate(parent)
          {
              artificial = new QTreeView(qobject_cast<QWidget*>(parent));
              artificial->setObjectName("DocumentTreeItems");
              artificial->setFixedSize(0, 0);
          }
          

          Thanks to that I can attach styles to this widget inside qss:

            #DocumentTreeItems::item {
              border: 1px solid transparent;
              border-radius: 2px;
              background-color: $primaryBackground;
          
              &:hover {
                border: 1px solid $contrastBorder;
                background-color: $controlWidgetBackground;
              }
          
              &:selected {
                border: 1px solid $accentBorder;
                background-color: $accentBackground;
              }
            }
          

          Then I can repaint the background using style and referring to my artificial widget in the paint method of delegate:

              style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, artificial);
          

          This gives the expected result:

          4704bbef-cb61-4bdd-9034-74854ca86f8f-image.png

          I'm however deeply dissatisfied with this solution, so if anyone knows a better one I'd be glad to hear suggestions.

          M Offline
          M Offline
          medyakovvit
          wrote on last edited by
          #4

          @kadet1090 What if to disable QStyle::State_Selected in the delegate paint function

          TreeWidgetItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
          {
              QStyleOptionViewItem  modifiedOption.state = option & ~QStyle::State_Selected;
              QStyledItemDelegate::paint(painter, modifiedOption, index);
          }
          
          kadet1090K 1 Reply Last reply
          0
          • M medyakovvit

            @kadet1090 What if to disable QStyle::State_Selected in the delegate paint function

            TreeWidgetItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
            {
                QStyleOptionViewItem  modifiedOption.state = option & ~QStyle::State_Selected;
                QStyledItemDelegate::paint(painter, modifiedOption, index);
            }
            
            kadet1090K Offline
            kadet1090K Offline
            kadet1090
            wrote on last edited by kadet1090
            #5

            @medyakovvit Delegate is used after problematic background is drawn, so fiddling with paint method won't help much. I can remove entire body of the paint method and the background will still be drawn. Not to say that it has nothing to do with selected state, as non selected items are also drawn incorrectly.

            1 Reply Last reply
            0
            • M Offline
              M Offline
              medyakovvit
              wrote on last edited by
              #6

              Seems I misunderstood the assignment)

              1 Reply Last reply
              0

              • Login

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