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. QStyledItemDelegate paint event on cell (not row) hover

QStyledItemDelegate paint event on cell (not row) hover

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 2 Posters 1.8k Views 2 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
    DaveK 0
    wrote on last edited by
    #1

    I have a custom QStyledItemDelegate that paints a QPixmap in a particular column. When that cell is hovered over with the mouse, I would like to paint it differently.

    Below is my paint event, which does paint the cell correctly when not State_MouseOver. However, it changes the color when I hover anywhere on the row. How can I make it change only when the mouse is hovering over the cell with the pixmap in it?

    void myDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        Q_ASSERT(index.isValid());
    
        switch(index.column()) {
            case DAY_COLUMN:
            {
                QSize btnSize = QSize(option.rect.height() * .9, option.rect.height() * .9);
                QRect r = option.rect;
                int x = r.right() - btnSize.width() - 10;
                int y = r.top();
                QRect btnRect = QRect(x, y, btnSize.width(), btnSize.height());
    
                QPixmap pixmap(":/icons/edit.png");
    
                // If hovered over, change color.
                if(option.state & QStyle::State_MouseOver) {
                    auto mask = pixmap.createMaskFromColor(QColor("Black"), Qt::MaskOutColor);
                    pixmap.fill(QColor("Red"));
                    pixmap.setMask(mask);
                }
    
                painter->drawPixmap(btnRect, pixmap, pixmap.rect());
    
                return;
            }
    
            /*.... draw other column(s) as appropriate ...*/
        }
    
    }
    

    I'm using this delegate on all rows withing a QTreeView.
    Qt 5.12

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      I have not tested this, but you can probably get the styled widget like this:

      const auto widget = qobject_cast<QWidget*>(option.styleObject);
      

      Then you can probably check if mouse is inside of it using:

      widget->rect().contains(mapFromGlobal(QCursor::pos()));
      

      (Z(:^

      1 Reply Last reply
      0
      • D Offline
        D Offline
        DaveK 0
        wrote on last edited by
        #3

        Thanks, that certainly seems to be on the right track. mapFromGlobal was not available within QStyledItemDelegate, so I used the created widget to call mapFromGlobal:

        widget->rect().contains(widget->mapFromGlobal(QCursor::pos()));
        

        However, the widget->rect() that is returned, is that of the treeView as a whole, not the cell. So it is always true, any time the cursor is inside the treeView.

        1 Reply Last reply
        0
        • sierdzioS Offline
          sierdzioS Offline
          sierdzio
          Moderators
          wrote on last edited by
          #4

          Hm, right. The delegates themselves are not QObjects, only QPainDevices. Well then, you can maybe get at this from the other side:

          • map cursor position to widget coordinates (like you do above)
          • then map option.rect to widget coordinates
          • then check if position is within the rect

          No idea if it will work, but maybe...

          (Z(:^

          1 Reply Last reply
          0
          • D Offline
            D Offline
            DaveK 0
            wrote on last edited by
            #5

            @sierdzio I was about to reply with something like that - I think this is close. The cell now changes color only when you hover over it, BUT it does not repaint if you move between cells within the same row. So you can move vertically between rows, and the cell will only change colors when you are over the pixmap - BUT if you move horizontally off of it, and back on, it does not repaint (and stays black).

            Is there a way I can force a re-paint when moving between columns?

            const auto widget = qobject_cast<QWidget*>(option.styleObject);
            auto cursorX = widget->mapFromGlobal(QCursor::pos()).x();
            
            // If hovered over, change color.
            if(option.state & QStyle::State_MouseOver && btnRect.contains(cursorX, btnRect.y())) {
                auto mask = pixmap.createMaskFromColor(QColor("Black"), Qt::MaskOutColor);
                pixmap.fill(QColor("Red"));
                pixmap.setMask(mask);
            }
            
            painter->drawPixmap(btnRect, pixmap, pixmap.rect());
            
            1 Reply Last reply
            0
            • sierdzioS Offline
              sierdzioS Offline
              sierdzio
              Moderators
              wrote on last edited by
              #6

              Is paint() not called at all when you move horizontally? Check with some debug messages.

              Also, print btnRect. cursorX, btnRect.y(), maybe it will offer some clues, perhaps paint() is called, but always thinks cursorX is within the rectangle?

              Is there a way I can force a re-paint when moving between columns?

              There must be some way, yeah. I'm not sure how to do it yet, though.

              (Z(:^

              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