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. How to set background color to currently selected row in QTableView using QStyledItemDelegate
Forum Updated to NodeBB v4.3 + New Features

How to set background color to currently selected row in QTableView using QStyledItemDelegate

Scheduled Pinned Locked Moved Unsolved General and Desktop
13 Posts 4 Posters 975 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.
  • D Offline
    D Offline
    dheerajshenoy
    wrote on last edited by dheerajshenoy
    #1

    I have a QTableView with a QStyledItemDelagate. The table will have number of columns determined at runtime by the user. I maintain a cursor row position representing the current index of the table. This is by default highlighted as selection color. I want to change the background of the row corresponding to cursor row position. I tried if (index.row() == cursor_row_pos) in the paint method of the delegate. But this only sets background for one column. How can I set background for the entire row ?

    I JonBJ 2 Replies Last reply
    0
    • D dheerajshenoy

      I have a QTableView with a QStyledItemDelagate. The table will have number of columns determined at runtime by the user. I maintain a cursor row position representing the current index of the table. This is by default highlighted as selection color. I want to change the background of the row corresponding to cursor row position. I tried if (index.row() == cursor_row_pos) in the paint method of the delegate. But this only sets background for one column. How can I set background for the entire row ?

      I Offline
      I Offline
      IgKh
      wrote on last edited by
      #2

      @dheerajshenoy said in How to set background color to currently selected row in QTableView using QStyledItemDelegate:

      QTableView

      Please show how you install the delegate, as well as a minimal version of the delegate class that reproduces the issue.

      1 Reply Last reply
      0
      • D dheerajshenoy

        I have a QTableView with a QStyledItemDelagate. The table will have number of columns determined at runtime by the user. I maintain a cursor row position representing the current index of the table. This is by default highlighted as selection color. I want to change the background of the row corresponding to cursor row position. I tried if (index.row() == cursor_row_pos) in the paint method of the delegate. But this only sets background for one column. How can I set background for the entire row ?

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #3

        @dheerajshenoy
        Is the row actually selected? If it is you could use Qt CSS on QTableView:

        The color and background of the selected item is styled using selection-color and selection-background-color respectively.

        Otherwise the paint() method is only called on what Qt decides needs repainting. For whatever reason it may be that it only thinks a single cell needs repainting where you actually want the whole row. You may need to raise the dataChanged() signal with role as Qt::BackgroundRole for the whole row when current/selection changes to make it redraw the whole row.

        It still would not do any harm to show your current code per @IgKh's post.

        1 Reply Last reply
        1
        • D Offline
          D Offline
          dheerajshenoy
          wrote on last edited by
          #4
          void paint(QPainter *painter, const QStyleOptionViewItem &option,
                     const QModelIndex &index) const override {
              if (!index.isValid())
                  return;
          
              QStyleOptionViewItem opt = option;
              initStyleOption(&opt, index);
          
              // Get the text and icon
              QString fileName = index.data(static_cast<int>(FileSystemModel::Role::FileName)).toString();
              QIcon icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
          
          
              // Draw the background
              QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
              style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
           
              // This draws only for the first column 
              if (index.row() == m_cursor_row) {
                  painter->save();
                  painter->fillRect(opt.rect, QColor(Qt::red));
                  painter->restore();
              }
          
              // Calculate rectangles
              QRect iconRect = opt.rect;
              iconRect.setWidth(opt.decorationSize.width());
          
              QRect textRect = opt.rect;
              textRect.setLeft(iconRect.right() + 4); // Add some padding after icon
          
              // Draw the icon if enabled in model
              if (!icon.isNull()) {
                  icon.paint(painter, iconRect, Qt::AlignCenter, QIcon::Normal, QIcon::Off);
              }
          
              QString symlinkTargetName = index.data(static_cast<int>(FileSystemModel::Role::Symlink)).toString();
          
              if (!symlinkTargetName.isEmpty()) {
          
                  // Draw filename
                  painter->setPen(opt.palette.color(QPalette::Text));
                  painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, fileName);
          
                  // Draw separator
                  int fileNameWidth = painter->fontMetrics().horizontalAdvance(fileName);
                  painter->drawText(textRect.adjusted(fileNameWidth, 0, 0, 0),
                                    Qt::AlignLeft | Qt::AlignVCenter, m_symlink_separator);
          
                  painter->save();
          
                  // Draw target path in the model's symlink color
                  painter->setFont(m_symlink_font);
          
                  int sepWidth = painter->fontMetrics().horizontalAdvance(m_symlink_separator);
                  int targetTextWidth = painter->fontMetrics().horizontalAdvance(symlinkTargetName);
                  int targetStartX = textRect.left() + fileNameWidth + sepWidth + 4;
                  QRect targetRect(targetStartX, textRect.top(),
                                   targetTextWidth,
                                   textRect.height());
          
                  if (!m_symlink_background.isEmpty()) {
                      painter->fillRect(targetRect, QColor(m_symlink_background));
                  }
          
                  painter->setPen(QPen(QColor(m_symlink_foreground)));
                  painter->drawText(textRect.adjusted(fileNameWidth + sepWidth + 4, 0, 0, 0),
                                    Qt::AlignLeft | Qt::AlignVCenter, symlinkTargetName);
          
                  painter->restore();
              } else {
                  // For non-symlink items, draw the full text
                  painter->setPen(opt.palette.color(QPalette::Text));
                  painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, fileName);
              }
          }
          
          JonBJ 1 Reply Last reply
          0
          • D dheerajshenoy
            void paint(QPainter *painter, const QStyleOptionViewItem &option,
                       const QModelIndex &index) const override {
                if (!index.isValid())
                    return;
            
                QStyleOptionViewItem opt = option;
                initStyleOption(&opt, index);
            
                // Get the text and icon
                QString fileName = index.data(static_cast<int>(FileSystemModel::Role::FileName)).toString();
                QIcon icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
            
            
                // Draw the background
                QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
                style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
             
                // This draws only for the first column 
                if (index.row() == m_cursor_row) {
                    painter->save();
                    painter->fillRect(opt.rect, QColor(Qt::red));
                    painter->restore();
                }
            
                // Calculate rectangles
                QRect iconRect = opt.rect;
                iconRect.setWidth(opt.decorationSize.width());
            
                QRect textRect = opt.rect;
                textRect.setLeft(iconRect.right() + 4); // Add some padding after icon
            
                // Draw the icon if enabled in model
                if (!icon.isNull()) {
                    icon.paint(painter, iconRect, Qt::AlignCenter, QIcon::Normal, QIcon::Off);
                }
            
                QString symlinkTargetName = index.data(static_cast<int>(FileSystemModel::Role::Symlink)).toString();
            
                if (!symlinkTargetName.isEmpty()) {
            
                    // Draw filename
                    painter->setPen(opt.palette.color(QPalette::Text));
                    painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, fileName);
            
                    // Draw separator
                    int fileNameWidth = painter->fontMetrics().horizontalAdvance(fileName);
                    painter->drawText(textRect.adjusted(fileNameWidth, 0, 0, 0),
                                      Qt::AlignLeft | Qt::AlignVCenter, m_symlink_separator);
            
                    painter->save();
            
                    // Draw target path in the model's symlink color
                    painter->setFont(m_symlink_font);
            
                    int sepWidth = painter->fontMetrics().horizontalAdvance(m_symlink_separator);
                    int targetTextWidth = painter->fontMetrics().horizontalAdvance(symlinkTargetName);
                    int targetStartX = textRect.left() + fileNameWidth + sepWidth + 4;
                    QRect targetRect(targetStartX, textRect.top(),
                                     targetTextWidth,
                                     textRect.height());
            
                    if (!m_symlink_background.isEmpty()) {
                        painter->fillRect(targetRect, QColor(m_symlink_background));
                    }
            
                    painter->setPen(QPen(QColor(m_symlink_foreground)));
                    painter->drawText(textRect.adjusted(fileNameWidth + sepWidth + 4, 0, 0, 0),
                                      Qt::AlignLeft | Qt::AlignVCenter, symlinkTargetName);
            
                    painter->restore();
                } else {
                    // For non-symlink items, draw the full text
                    painter->setPen(opt.palette.color(QPalette::Text));
                    painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, fileName);
                }
            }
            
            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @dheerajshenoy said in How to set background color to currently selected row in QTableView using QStyledItemDelegate:

            // This draws only for the first column

            So I would suggest as per my previous that Qt is only calling for a single column in the row to be redrawn while you wish the whole row to change background, and what it looks like you need to do about that.

            You did not even even comment on

            Is the row actually selected? If it is you could use Qt CSS on QTableView:

            I can only guess not from no response.

            D 1 Reply Last reply
            0
            • JonBJ JonB

              @dheerajshenoy said in How to set background color to currently selected row in QTableView using QStyledItemDelegate:

              // This draws only for the first column

              So I would suggest as per my previous that Qt is only calling for a single column in the row to be redrawn while you wish the whole row to change background, and what it looks like you need to do about that.

              You did not even even comment on

              Is the row actually selected? If it is you could use Qt CSS on QTableView:

              I can only guess not from no response.

              D Offline
              D Offline
              dheerajshenoy
              wrote on last edited by
              #6

              @JonB Sorry I missed on the detail of the selection. Yes it is selected. I am working on a keyboard driven file manager (similar ranger, yazi etc.). The current row is always selected. When the user goes to select multiple rows I want the current cursor row to be in a particular color to let the user know which row they are currently on.

              1 Reply Last reply
              0
              • D Offline
                D Offline
                dheerajshenoy
                wrote on last edited by
                #7

                I see the problem now, I have set the delegate for column using setItemDelegateForColumn. Changing this would solve my problem.

                1 Reply Last reply
                1
                • D dheerajshenoy has marked this topic as solved on
                • D dheerajshenoy has marked this topic as unsolved on
                • D Offline
                  D Offline
                  dheerajshenoy
                  wrote on last edited by
                  #8
                  if (index.row() == m_cursor_row) {
                      // Custom color for the cursor row
                      painter->fillRect(opt.rect, QColor("#ADD8E6")); // Light blue
                  } else if (option.state & QStyle::State_Selected) {
                      // Default selection color
                      QPalette::ColorRole selectionRole = QPalette::Highlight;
                      QColor selectionColor = opt.palette.color(selectionRole);
                      painter->fillRect(opt.rect, selectionColor);
                  }
                  

                  The background is applied correctly now to the current cursor position, but the other rows are not highlighted completely.

                  20c8ac47-dab1-4939-b8c5-d1852e79b4d8-image.png

                  The light blue color is the current row and the rest are selected items. You can see that the other columns are not redrawn correctly. But when the application loses focuses the other columns are drawn correctly.

                  JonBJ 1 Reply Last reply
                  0
                  • D dheerajshenoy
                    if (index.row() == m_cursor_row) {
                        // Custom color for the cursor row
                        painter->fillRect(opt.rect, QColor("#ADD8E6")); // Light blue
                    } else if (option.state & QStyle::State_Selected) {
                        // Default selection color
                        QPalette::ColorRole selectionRole = QPalette::Highlight;
                        QColor selectionColor = opt.palette.color(selectionRole);
                        painter->fillRect(opt.rect, selectionColor);
                    }
                    

                    The background is applied correctly now to the current cursor position, but the other rows are not highlighted completely.

                    20c8ac47-dab1-4939-b8c5-d1852e79b4d8-image.png

                    The light blue color is the current row and the rest are selected items. You can see that the other columns are not redrawn correctly. But when the application loses focuses the other columns are drawn correctly.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by
                    #9

                    @dheerajshenoy
                    Like for your discovery about setItemDelegateForColumn(), start by verifying how you select and what your QAbstractItemView::SelectionBehavior is set to: looks like the default is QAbstractItemView::SelectItems "Selecting single items.", have you set QAbstractItemView::SelectRows?

                    1 Reply Last reply
                    0
                    • Christian EhrlicherC Offline
                      Christian EhrlicherC Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      The last 'column' does not look like a column but empty space --> setStretchLastSection(true)

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

                      JonBJ 1 Reply Last reply
                      1
                      • Christian EhrlicherC Christian Ehrlicher

                        The last 'column' does not look like a column but empty space --> setStretchLastSection(true)

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by
                        #11

                        @Christian-Ehrlicher
                        Fair enough, but because OP ends up with light blue there but not darker blue that implies that the opt.rect passed into his code for fillRect() are not covering the same area? Why not? Why should he need/have to stretch last section?

                        Christian EhrlicherC 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @Christian-Ehrlicher
                          Fair enough, but because OP ends up with light blue there but not darker blue that implies that the opt.rect passed into his code for fillRect() are not covering the same area? Why not? Why should he need/have to stretch last section?

                          Christian EhrlicherC Offline
                          Christian EhrlicherC Offline
                          Christian Ehrlicher
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          @JonB said in How to set background color to currently selected row in QTableView using QStyledItemDelegate:

                          Why should he need/have to stretch last section?

                          As you can see the last 'section' has no header title so I assume it's no column at all but empty space.

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

                          JonBJ 1 Reply Last reply
                          0
                          • Christian EhrlicherC Christian Ehrlicher

                            @JonB said in How to set background color to currently selected row in QTableView using QStyledItemDelegate:

                            Why should he need/have to stretch last section?

                            As you can see the last 'section' has no header title so I assume it's no column at all but empty space.

                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on last edited by JonB
                            #13

                            @Christian-Ehrlicher
                            Yes. And my point is that was done via previously making that the current row via the code above at https://forum.qt.io/post/818550. Which is also used for coloring the selected row. And they both get passed an opt.rect for fillrect(). So presumably the rect for the selection is wider than the rect for his cursor row to produce the result. But why are they different widths or cover different cells?

                            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