Qt委托设置鼠标悬停状态的复选框

Qt delegate setting mouseover state for checkbox

本文关键字:状态 复选框 悬停 鼠标 设置 Qt      更新时间:2023-10-16

我在QTableview中使用的委托中有一个paint方法,我在其中向单元格添加了一个复选框指示器。当我通过检查选项进入单元格时,很容易设置复选框的鼠标悬停状态。状态QStyle::State_MouseOver标志,但我理想情况下需要做的是,当鼠标指针在指示器本身之上,而不仅仅是在单元格周围悬停时,只设置复选框指示器的鼠标悬停状态。不幸的是,油漆方法仅在当前从一个单元格移动到另一个单元格时触发,因此我需要一些关于如何做到这一点的指针。

代码如下(其中mouse_pointer_是最后存储的鼠标坐标):

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);
}

经过一番调查,我发现问题是我的editorEvent()方法需要返回true(表明单元格内容已经更改)来强制重新绘制单元格,从而设置所选状态。代码如下:

 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;
}

更简单

bool hover = option.state & QStyle::State_MouseOver;
if (hover) {
    painter->fillRect(r, QColor(0,0,0,10));
}