如何更改QTreeView头部的背景颜色?
我想改变某些标题部分的背景颜色。有些部分会使用默认颜色,而其他部分则会用不同的颜色。
HeaderView不像QTreeView那样接受委托,它自己负责所有的绘制工作。它通过两个方法来完成这个任务:
我最开始的尝试是重写paintSection方法,让它先绘制默认的内容,然后再添加我自己的内容。
def paintSection(self, painter, rect, logicalindex):
QHeaderView.paintSection(self, painter, rect, logicalindex)
painter.save()
painter.fillRect(rect, QBrush(Qt.red))
painter.restore()
但是这样似乎没有任何效果。它不会绘制填充的矩形。如果我把调用基类的paintSection方法的那一行注释掉,它会绘制填充的矩形,但效果不太稳定(比如,点击和调整标题的大小时,有时会填充,有时又不会)。
任何帮助都非常感谢。
3 个回答
我觉得你不需要重写什么东西。可以看看 palette
这个属性,它是 QWidget 的一个属性。
我同意“Harald Scheirich”的观点,样式表确实是个好东西。不过为了让你更信服,我想跟你聊聊样式表中一个不太为人所知的部分,叫做属性选择器。
如果你去看看样式表的文档,这里有一小段关于它们的介绍。简单来说,我们可以为那些具有特定属性的控件指定样式表。比如说,所有的QPushButton按钮如果是扁平的。
QPushButton[flat="true"]
{
background-color: blue
}
虽然这听起来很酷,但光这样并不能帮到你。更神奇的是,你可以给QObject添加自己的属性。这些叫做动态属性,也可以在属性选择器中使用。
所以我可以创建一个这样的样式表——其中highlightHeader是我自己虚构的属性。
QHeaderView[highlightHeader="true"]
{
background-color: red
}
现在,你可以把这个样式表应用到每一个QHeaderView上。但因为没有人把highlightHeader设置为true,所以我们不会在任何地方看到红色。因此,下一步是当我们决定要把某个特定的QHeaderView变成红色时,我们就调用这个:
myHeaderView->setProperty("highlightHeader", true);
myHeaderView->style()->unpolish(myHeaderView);
myHeaderView->style()->polish(myHeaderView);
在第一行中,我们设置了一个属性来触发我们想要的状态。接下来的两行是为了确保Qt重新评估这个控件的样式。否则你可能看不到变化。
基本上就是这样。希望这对你有帮助。
其实你不需要实现什么,QHeaderView
可以通过样式表来修改,就像大多数控件一样。
补充:
你提到想根据数据来改变每一列的背景颜色,最简单的方法可能是从QAbstractItemModel
或者其他模型类派生一个新模型,然后重新实现headerData()
这个函数。
QVariant QAbstractItemModel::headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const [virtual]
你想要响应的角色是Qt::BackgroundColorRole
,所以这个函数可能看起来像这样:
QVariant VariableHeaderModel::headerData(int section Qt::Orientation orientation, int role)
{
QVariant result;
if (role == Qt::BackgroundColorRole)
{
result = <QColor from custom processing>
}
else
{
result = Superclass::headerData(section, orientation, role);
}
return result;
}
一般来说,在Qt中,模型决定显示什么,通常情况下是改变模型,而不是视图。而且'data()'这个函数会被调用很多次,我不太清楚'headerData()'的情况,但如果有很多计算的话,你可能想要缓存一下结果。
如果你使用的是QStandardItemModel
,你可能只需要调用:
setHeaderData(section, orientation, <aColor>, Qt::BackgroundColorRole);