需要实现QTableview鼠标悬浮时当前行高亮显示。但是实现的过程中发现一开始的方案不能用,必须捕捉鼠标的move事件通过Delegate自己绘制背景实现。一开始想通过重载Delegate里面的editorEvent捕捉。后面发现鼠标的move事件可以捕捉的到,但是leave事件获取不到,这样就会造成鼠标移出表格始终又一行高亮。后面只能通过继承QTableview捕捉到鼠标事件,然后通过delegate绘制的方法实现。
在Qt4中可以直接设置item的悬停(hover)事件,如下所示:
QTableView::item:hover {
background-color: rgba(200,200,220,255);
}
然后在tableview的属性中设置selectionMode和selectionBehavior的属性为每次选中一行。
ui.TableView->setSelectionBehavior(QAbstractItemView::SelectRows);
ui.TableView->setSelectionMode(QAbstractItemView::SingleSelection);
结果发现在Qt5中样式表设置的样式不能生效。所以只能另找方案。
在stackoverflow上面查了有人提供了下面的方案:
- You can use delegates to draw the row background…
You will need to set the row to highlight in the delegate and based on that, do the highlighting.- Catch the signal of current row. Iterate over the items in that row and set background for each item.
翻译一下就是捕捉当前鼠标悬浮(hover)行的信号,使用委托绘制行背景。
bool CRoomMemDelegate::editorEvent(QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index)
{
if (event->type() == QEvent::MouseMove)//鼠标移动事件
{
m_selectionRow = index.row();
}
else if(event->type() == QEvent::leave)//离开事件
{
m_selectionRow = -1;
}
return false;
}
如上尝试了通过m_selectionRow 保存当前悬停的行,然后在paint函数里面进行绘制背景。不过调试中发现mousemove动作可以捕获的到,但是leave事件得不到。所以会导致无论如何都会有一行被选中。
为了能够捕捉到鼠标的事件,子类话了QTableview,然后通过信号告诉QStyledItemDelegate鼠标的move/leave的动作。这个信号把悬停的当前行的信息发送出去。QStyledItemDelegate获取到hoving的行,保存当前行的信息并触发paint的动作进行绘制。具体的操作代码如下:
//1: Tableview :
void TableView::mouseMoveEvent(QMouseEvent *event)
{
QModelIndex index = indexAt(event->pos());
emit hoverIndexChanged(index);
...
}
//2.connect signal and slot
connect(this,SIGNAL(hoverIndexChanged(const QModelIndex&)),delegate_,SLOT(onHoverIndexChanged(const QModelIndex&)));
//3.onHoverIndexChanged
void TableViewDelegate::onHoverIndexChanged(const QModelIndex& index)
{
hoverrow_ = index.row();
}
//4.in Delegate paint():
void TableViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
...
if(index.row() == hoverrow_)
{
//HERE IS HOVER COLOR
painter->fillRect(option.rect, kHoverItemBackgroundcColor);
}
else
{
painter->fillRect(option.rect, kItemBackgroundColor);
}
...
}
上面的代码少了一个步骤就是触发paint绘制的动作,这个可以调用model里面的dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles = …)函数刷新对应行的信息。
1、How to highlight the entire row on mouse hover in QTableWidget: Qt5
2、QTableView How can I highlight the entire row for mouse hover?