所以我能够自己解决这个问题。 (毫无意义的赏金,我不知道为什么我在检查它是否有效之前交出了 50 个代表。)
我所做的是继承 QStyledItemDelegate 并重新实现 paint() 函数。
.h
class MyStyledItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit MyStyledItemDelegate(QObject *parent = 0){}
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
}
在这个绘制函数中,我能够检查索引的 UserRoles 是否有自定义标志来决定我想要的颜色。我可以使用QStyle::State_Selected 和QStyle::State_MouseOver 检查索引是否被选中或悬停。使用该信息,我能够编写逻辑来确定我想要的颜色。之后,我不得不手动绘制背景、图标和文本。
.cpp
void MyStyledItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//background
QColor bgColor;
int bgColorType(0);
bgColorType = index.data(Qt::UserRole+9).toInt();//custom flag I set to determine which color i want
//color logic
if(bgColorType == 0)
bgColor = QColor(Qt::transparent);//default is transparent to retain alternate row colors
else if(bgColorType == 1)
bgColor = qRgba(237, 106, 106, 255);//red
else if(bgColorType == 2)
bgColor = qRgba(241, 167, 226, 255);//pink
//etc...
QStyleOptionViewItem opt(option);
if(option.state & QStyle::State_Selected)//check if item is selected
{
//more color logic
if(bgColorType == 0)
bgColor = qRgba(190, 220, 240, 255);
else
bgColor = qRgba(bgColor.red()-25, bgColor.green()-25, bgColor.blue()-25, 255);
//background color won't show on selected items unless you do this
opt.palette.setBrush(QPalette::Highlight, QBrush(bgColor));
}
if(option.state & QStyle::State_MouseOver)//check if item is hovered
{
//more color logic
bgColor = qRgba(bgColor.red()-25, bgColor.green()-25, bgColor.blue()-25, 255);
if(option.state & QStyle::State_Selected)//check if it is hovered AND selected
{
//more color logic
if(bgColorType == 0)
{
bgColor = qRgba(148, 200, 234, 255);
}
//background color won't show on selected items unless you do this
opt.palette.setBrush(QPalette::Highlight, QBrush(bgColor));
}
}
//set the backgroundBrush to our color. This affects unselected items.
opt.backgroundBrush = QBrush(bgColor);
//draw the item background
option.widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);
//icon
QRect iconRect = option.rect;
iconRect.setLeft(iconRect.left()+3);//offset it a bit to the right
//draw in icon, this can be grabbed from Qt::DecorationRole
//altho it appears icons must be set with setIcon()
option.widget->style()->drawItemPixmap(painter, iconRect, Qt::AlignLeft | Qt::AlignVCenter, QIcon(index.data(Qt::DecorationRole).value<QIcon>()).pixmap(16, 16));
//text
QRect textRect = option.rect;
textRect.setLeft(textRect.left()+25);//offset it a bit to the right
//draw in text, this can be grabbed from Qt::DisplayRole
option.widget->style()->drawItemText(painter, textRect, Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, index.data(Qt::DisplayRole).toString());
}
完成后,我只需将代理应用到我的QTreeView 和myTreeView->setItemDelegate(new MyStyledItemDelegate(myTreeView));
不需要样式表、后台角色更改或事件过滤器。我在整个互联网上搜索了一个解决方案,只发现很多人有同样的问题并且没有好的答案。这是迄今为止我想出的最简单和最通用的方法,所以我希望它可以帮助其他需要它的人:)