What does QHeaderView::paintSection do such that a

2020-02-01 12:54发布

问题:

This question is further development of this post and is different, though may seem similar as this one.

I am trying to reimplement QHeaderView::paintSection, so that the background returned from the model would be honored. I tried to do this

void Header::paintSection(QPainter * painter, const QRect & rect, int logicalIndex) const
{
    QVariant bg = model()->headerData(logicalIndex, Qt::Horizontal, Qt::BackgroundRole);
    // try before
    if(bg.isValid())                // workaround for Qt bug https://bugreports.qt.io/browse/QTBUG-46216
        painter->fillRect(rect, bg.value<QBrush>());             
    QHeaderView::paintSection(painter, rect, logicalIndex);
    // try after
    if(bg.isValid())                // workaround for Qt bug https://bugreports.qt.io/browse/QTBUG-46216
        painter->fillRect(rect, bg.value<QBrush>());             
}

However, it didn't work - if I make QHeaderView::paintSection call, nothing I draw with the painter is visible (I also tried drawing a diagonal line). If I remove QHeaderView::paintSection call, the line and the background will be visible. Making the fillRect call before vs. after the QHeaderView::paintSection doesn't make any difference.

I wonder, what is it that QHeaderView::paintSection does that makes it impossible for me to draw something on top of it. And whether there is a way to overcome it without reimplementing everythning what QHeaderView::paintSection does?

All I need to do is to add a certain shade to a certain cell - I still want everything in the cell (text, icons, gradient background etc.) to be painted as it is now...

回答1:

It is obvious why the first fillRect doesn't work. Everything that you paint before paintSection is overridden by base painting.

The second call is more interesting.

Usually all paint methods preserves painter state. It means that when you call paint it looks like the painter state hasn't been changed.

Nevertheless QHeaderView::paintSection spoils the painter state.

To bypass the issue you need to save and restore the state by yourself:

void Header::paintSection(QPainter * painter, const QRect & rect, int logicalIndex) const
{
    QVariant bg = model()->headerData(logicalIndex, Qt::Horizontal, Qt::BackgroundRole);
    painter->save();
    QHeaderView::paintSection(painter, rect, logicalIndex);
    painter->restore();
    if(bg.isValid())               
        painter->fillRect(rect, bg.value<QBrush>());             
}