Question

I have a paint method in a delegate used in a QTableview where I add a checkbox indicator to a cell. Its very easy to set the mouseover state of the checkbox when I enter the cell by checking the option.state for the QStyle::State_MouseOver flag but what I ideally need to do is only set the mouseover state for the checkbox indicator when the mouse pointer is over the indicator itself and not just hovering around the cell. Unfortunately the paint method is only triggered when moving from one cell to the other at present so I need some pointers on how to do this.

Code is as follows (where mouse_pointer_ is the last stored mouse coordinates):

void
CheckBoxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
                            const QModelIndex& index) const
{

   // Draw our checkbox indicator
   bool value = index.data(Qt::DisplayRole).toBool();
   QStyleOptionButton checkbox_indicator;

   // Set our button state to enabled
   checkbox_indicator.state |= QStyle::State_Enabled;
   checkbox_indicator.state |= (value) ? QStyle::State_On : QStyle::State_Off;

   // Get our dimensions
   checkbox_indicator.rect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkbox_indicator, NULL );

   // Position our indicator
   const int x = option.rect.center().x() - checkbox_indicator.rect.width() / 2;
   const int y = option.rect.center().y() - checkbox_indicator.rect.height() / 2;

   checkbox_indicator.rect.moveTo(x, y);

   if (checkbox_indicator.rect.contains(mouse_position_)) {
      checkbox_indicator.state |= QStyle::State_MouseOver; 
   }

   QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkbox_indicator, painter);
}

Any help would be much appreciated.

Was it helpful?

Solution

After some investigation I found that the issue was that my editorEvent() method needed to return true (indicating that the cell contents have changed) to force the repaint of the cell and thus set the selected state. Code is below:

 bool CheckBoxDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
 {
    bool repaint_cell = false;  

    QMouseEvent *e = static_cast<QMouseEvent *> (event);

    mouse_position_ = e->pos();

    // We need to check if the mouse pointer is hovering within 
    // the checkbox indicator area of the table cell
    QStyleOptionButton checkbox_indicator;  
    checkbox_indicator.rect = QApplication::style()->subElementRect( QStyle::SE_CheckBoxIndicator, &checkbox_indicator, NULL );
    const int x = option.rect.center().x() - checkbox_indicator.rect.width() / 2;
    const int y = option.rect.center().y() - checkbox_indicator.rect.height() / 2;
    checkbox_indicator.rect.moveTo(x, y );

    if (checkbox_indicator.rect.contains(mouse_position_)) {
        repaint_cell  = true;   

        // Check if the user has clicked in this area
        if (e->button() == Qt::LeftButton) {    

            switch(event->type()) {
                case QEvent::MouseButtonRelease: 
                    // Update model data in here
                    break;
                default:
                    break;
            }
        }

    }

    return repaint_cell;
}

OTHER TIPS

more simple

bool hover = option.state & QStyle::State_MouseOver;
if (hover) {
    painter->fillRect(r, QColor(0,0,0,10));
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top