关于qt:QTreeView绘制行的颜色

QTreeView color of painted row

我扩展了一个 QStyledItemDelegate 以在 QTreeView 的右侧绘制一些像素图。这很好用,但是,我意识到如果像素图太长,它可以在文本前面。
enter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void MyItemDelegate::paint(
    QPainter *painter,
    const QStyleOptionViewItem &option,
    const QModelIndex &index) const
{
    ...
    QStyledItemDelegate::paint(painter, option, index);
    ...
    QStyleOptionViewItem opt = option;
    initStyleOption(&opt, index);
    ...
    painter->fillRect(rect, opt.backgroundBrush);
    painter->drawPixmap(topLeft, pixmap);
}

我知道除了 opt.backgroundBrush 之外的所有变量都是正确的。无论有没有 initStyleOption 调用,它总是不可见的黑色。

然后我开始检查 opt.stateopt.features 的值来自己挑选颜色。我在交替颜色 (QStyleOptionViewItem::Alternate) 方面取得了一些成功,但它开始变得冗长乏味,因为还有其他状态(悬停和选择)和其他操作系统可能有其他状态。一定有更简单的方法。

所以,我的问题是:当我在 paint 方法中时,如何获得用于绘制行的实际颜色?或者,您还有其他干净的方法来避免这种情况吗?


正如@G.M. 所建议的那样。我使用了 QItemDelegate 类而不是 QStyledItemDelegate 并且我对绘图过程有更多的控制权。尤其是因为添加了像 drawDisplay 这样的受保护函数。覆盖此方法,我可以将"显示矩形"调整为比 Qt 计算的更小。

1
2
3
4
5
6
7
8
9
10
void ActionsItemDelegate::drawDisplay(
    QPainter *painter,
    const QStyleOptionViewItem &option,
    const QRect &rect,
    const QString &text) const
{
    const int minX = ...; // x position of the left-most icon
    const int iconsWidth = rect.width() - (minX - rect.x());
    QItemDelegate::drawDisplay(painter, option, rect.adjusted(0, 0, -iconsWidth, 0), text);
}

缺点是使用 QStyledItemDelegate 时 UI 会发生变化。我不知道如何获得两者的好处:普通样式和更多控件。


我可能会有不同的处理方式。我不会先打电话:

1
QStyledItemDelegate::paint(painter, option, index);

首先。

然后,重要的部分:如果你知道你的物品上有多少图标,你就可以计算出边界矩形。

你怎么知道你有多少个图标?也许通过调用类似:

1
bool hasIcon = index->data(YourAPP::HasIcons).toBool();

你的委托中可以有这样的东西:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void MyItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
...
QStyleOptionViewItem o = option;
initStyleOption(&o, index);
bool hasIcon = index->data(YourModel::HasIcons).toBool();
// or
bool hasCustomRole1 = index->data(YourModel::Role1).toBool();
bool hasCustomRole2 = index->data(YourModel::Role2).toBool();

if (hasIcon) {
    // width of your icons, can be like o.rect.height() * numbers of icons
    int width = 0;

    // shrink your first rectangle
    o.rect.adjust(0, 0, -width, 0);

    // create a second rectangle
    QStyleOptionViewItem o2 = option;
    initStyleOption(&o2, index);
    o2.rect.adjust(width, 0, 0, 0);

    // paint your icons
    ...
    painter->drawPixmap(o2, pixmap);
} else {
    QStyledItemDelegate::paint(painter, option, index);
}