Changing the row background color of a QTreeView does not work
Solution 1
If the only problem is that the expanding/collapsing controls do not have a background like rest of the row then use Qt::BackgroundRole
in ::data()
of your model (as described by pnezis in their answer) and add this to your tree view class:
void MyTreeView::drawBranches(QPainter* painter,
const QRect& rect,
const QModelIndex& index) const
{
if (some condition depending on index)
painter->fillRect(rect, Qt::red);
else
painter->fillRect(rect, Qt::green);
QTreeView::drawBranches(painter, rect, index);
}
I've tested this on Windows (Vista and 7) using Qt 4.8.0 and expanding/collapsing arrows have proper background. The problem is that those arrows are part of the view and thus cannot be handled in a model.
Solution 2
Instead of subclassing QTreeView
you should handle the background color through your model. Use the data()
function and the Qt::BackgroundRole
for changing the background color of the rows.
QVariant MyModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::BackgroundRole)
{
if (condition1)
return QColor(Qt::red);
else
return QColor(Qt::green);
}
// Handle other roles
return QVariant();
}
SebastianK
Interested in algorithms, operations research, scheduling, C++
Updated on July 18, 2022Comments
-
SebastianK almost 2 years
I have a
QTreeView
and want different background colors for rows, depending on their content. To achieve this, I derived aclass MyTreeView
fromQTreeView
and implemented the paint method as follows:void MyTreeView::drawRow (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QStyleOptionViewItem newOption(option); if (someCondition) { newOption.palette.setColor( QPalette::Base, QColor(255, 0, 0) ); newOption.palette.setColor( QPalette::AlternateBase, QColor(200, 0, 0) ); } else { newOption.palette.setColor( QPalette::Base, QColor(0, 0, 255) ); newOption.palette.setColor( QPalette::AlternateBase, QColor(0, 0, 200) ); } QTreeView::drawRow(painter, newOption, index); }
Initially, I set
setAlternatingRowColors(true);
for the QTreeView.My problem: Setting the color for QPalette::Base has no effect. Every second row remains white.
However, setting QPalette::AlternateBase works as expected. I tried
setAutoFillBackground(true)
andsetAutoFillBackground(false)
without any effect.Are there any hints how to solve this problem? Thank you.
Remark: Setting the color by adapting
MyModel::data(const QModelIndex&, int role)
forQt::BackgroundRole
does not provide the desired result. In this case, the background color is used only for a part of the row. But I want to color the full row, including the left side with the tree navigation stuff.Qt Version: 4.7.3
Update: For unknown reasons
QPalette::Base
seems to be opaque. setBrush does not change that. I found the following workaround:if (someCondition) { painter->fillRect(option.rect, Qt::red); newOption.palette.setBrush( QPalette::AlternateBase, Qt::green); } else { painter->fillRect(option.rect, Qt::orange); newOption.palette.setBrush( QPalette::AlternateBase, Qt:blue); }
-
SebastianK over 11 yearsI tried this, but this does not yield desired result. With this approach, the background color is not painted for the full row, but only for the tree items itself. The background of the tree navigation (on the left side of the items) is not changed.
-
Tim Meyer over 11 years@SebastianK I think this is still the right way, but the way you implement
condition1
in this example is the key. For example, you could doif( index.sibling( index.row(), someColumnIndex ).data() == whatever ) { ... }
. You have to make sure this is not called for the case whereindex.column() == someColumnIndex
as of infinite recursion of course. -
SebastianK over 11 years@TimMeyer I tried that with
condition1
beeing always true. The background of the row was only partially red. For expanded items, the left part of the row is still white. With "left part" I mean the area with the tree navigation stuff (expanding/collapsing [+]/[-] and the line to parent) -
SebastianK over 11 yearsThank you for your answer. As you said, the drawback of this solution is that it is scattered between Model and View. But the idea with
fillRect
lead me to a reasonable workaround. -
Wojciech Cierpucha over 11 yearsI agree, in this case it might be better to have coloring code only in the view - overriding other drawXXX member functions. I'm glad I could help.