1.效果图
2.下载链接
QListView(仿网易云本地音乐列表)
3.关键代码
void ListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QPixmap *playIcon = nullptr;
QPixmap *collectionIcon = nullptr;
QPixmap *commentIcon = nullptr;
QPixmap *moreIcon = nullptr;
m_eventType = -1;
auto [textRects,btnRects] = calculateRectArea(option.rect);
const bool isHover = option.state.testFlag(QStyle::State_MouseOver);
const QPoint globalPos = QCursor::pos();
const QPoint mousePos = m_listView->mapFromGlobal(globalPos);
Qt::CursorShape cursorShape = Qt::ArrowCursor;
QString tipText;
if(isHover)
{
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(QBrush(QColor(255,255,255)));
painter->drawRoundedRect(option.rect,10,10);
painter->restore();
}
if(isHover)
{
if(btnRects[kPlay].contains(mousePos))
{
cursorShape = Qt::PointingHandCursor;
tipText = "播放";
playIcon = m_iconPixmaps[kPlayHover];
m_eventType = kPlay;
}
else
{
playIcon = m_iconPixmaps[kPlayNormal];
}
}
else
{
painter->drawText(textRects[kSn],Qt::AlignCenter,QString("%1").arg(index.row(),2,10,QChar('0')));
}
QString title = index.data(Qt::UserRole).toString();
painter->drawText(textRects[kTitle],Qt::AlignVCenter,title);
if(textRects[kTitle].contains(mousePos))
{
QStringList strList = title.split("\n");
if(mousePos.y()<option.rect.center().y()) tipText = strList[0];
else tipText = strList[1];
}
if(isHover)
{
collectionIcon = m_iconPixmaps[kCollectionNormal];
commentIcon = m_iconPixmaps[kCommentNormal];
moreIcon = m_iconPixmaps[kMoreNormal];
if(!tipText.isEmpty())
{
}
else if(btnRects[kCollection].contains(mousePos))
{
cursorShape = Qt::PointingHandCursor;
tipText = "收藏";
collectionIcon = m_iconPixmaps[kCollectionHover];
m_eventType = kCollection;
}
else if(btnRects[kComment].contains(mousePos))
{
cursorShape = Qt::ForbiddenCursor;
tipText = "评论";
}
else if(btnRects[kMore].contains(mousePos))
{
cursorShape = Qt::PointingHandCursor;
tipText = "更多";
moreIcon = m_iconPixmaps[kMoreHover];
m_eventType = kMore;
}
}
QString album = index.data(Qt::UserRole+1).toString();
painter->drawText(textRects[kAlbum],Qt::AlignCenter,album);
QString duration = index.data(Qt::UserRole+2).toString();
painter->drawText(textRects[kDuration],Qt::AlignCenter,duration);
QString size = index.data(Qt::UserRole+3).toString();
painter->drawText(textRects[kSize],Qt::AlignCenter,size);
if(playIcon!=nullptr) painter->drawPixmap(btnRects[kPlay],*playIcon);
if(collectionIcon!=nullptr) painter->drawPixmap(btnRects[kCollection],*collectionIcon);
if(commentIcon!=nullptr) painter->drawPixmap(btnRects[kComment],*commentIcon);
if(moreIcon!=nullptr) painter->drawPixmap(btnRects[kMore],*moreIcon);
QApplication::setOverrideCursor(cursorShape);
if(tipText.isEmpty()) QToolTip::hideText();
else QToolTip::showText(globalPos,tipText,m_listView);
}
QSize ListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return QSize(option.rect.width(),85);
}
bool ListDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
if(event->type() == QEvent::MouseMove)
{
return true;
}
else if(event->type() == QEvent::MouseButtonPress)
{
QMouseEvent *me = static_cast<QMouseEvent*>(event);
if(me->button() == Qt::LeftButton)
{
if(m_eventType==kPlay) emit playBtnClicked(index.row());
else if(m_eventType==kCollection) emit collectionBtnClicked(index.row());
else if(m_eventType==kMore) emit moreBtnClicked(index.row());
}
}
else if(event->type() == QEvent::MouseButtonDblClick)
{
QMouseEvent *me = static_cast<QMouseEvent*>(event);
if(me->button() == Qt::LeftButton)
{
emit playBtnClicked(index.row());
}
}
return QStyledItemDelegate::editorEvent(event,model,option,index);
}
QPair<QVector<QRect>,QVector<QRect>> ListDelegate::calculateRectArea(const QRect &area) const
{
QVector<QRect> textRects(kTextCount);
for(int i =0;i<textRects.size();++i)
{
int left = (i==0 ? 0 : textRects[i-1].right()+1);
int width = 0;
if(i==kSn)
{
width = kTitleWidth;
}
else if(i==kTitle)
{
width = area.width() - (kTitleWidth + (kSize-kHide+1)*kBaseWidth);
}
else
{
width = kBaseWidth;
}
textRects[i] = QRect(left,area.top(),width,area.height());
}
QVector<QRect> btnRects(kBtnCount);
const int top = (area.height() - kIconSize)/2 + area.top();
QVector<int> vx(kBtnCount);
vx[kPlay] = (textRects[kSn].width() - kIconSize)/2 + textRects[kSn].left();
const int count = (kMore-kCollection+1);
const int interval = (kBaseWidth-count*kIconSize)/(count+1);
for(int i =kCollection;i<=kMore;++i)
{
if(i==kCollection)
{
vx[i] = textRects[kHide].left() + interval;
}
else
{
vx[i] = vx[i-1] + kIconSize + interval;
}
}
for(int i =0;i<vx.size();++i)
{
btnRects[i] = QRect(vx[i],top,kIconSize,kIconSize);
}
return qMakePair(textRects,btnRects);
}