在 Qt 6.5 之前,仅当指定了项目的交替背景时才会渲染项目背景,从而允许
QStyledItemDelegate
独立渲染背景。然而,这已被 qt/qtbase@16e0e7c 提交更改。
编辑:我发现了另一个属于此回归的提交:qt/qtbase@483ae6c。这个将
PanelItemViewRow
s 转换为 PanelItemViewItem
s 来“正确”渲染背景,因为它是不可从 qss 设置样式的。我不知道为什么这样做而不是在 qss 中引入像 ::row
这样的东西。
一种解决方案是使用
PE_PanelItemViewRow
覆盖 QProxyStyle
但这不适用于样式表,这是硬性要求,因为应用程序允许自定义样式。
另一种可能性是在 qss 中将
::item
设置为没有背景,并以某种方式在 QStyledItemDelegate
中渲染它,但我不知道如何以可以使用 qss 控制它的方式进行操作。
不正确的行为:
预期的一个:
我设法找到了解决这个问题的办法。
要禁用背景渲染,我可以在 Qt 中滥用此 if 语句:
// For compatibility reasons, QTreeView draws different parts of
// the background of an item row separately, before calling the
// delegate to draw the item. The row background of an item is
// however not separately styleable through a style sheet, but
// only indirectly through the background of the item. To get the
// same background for all parts drawn by QTreeView, we have to
// use the background rule for the item here.
if (renderRule(w, opt, PseudoElement_ViewItem).hasBackground())
pseudoElement = PseudoElement_ViewItem;
因此禁用
::item
的背景会禁用分支和不需要的背景的渲染(我正在使用qtsass):
QTreeView::item {
&, &:selected, &:hover {
background: none;
border: none;
}
}
然而,这使我无法定义 qss 的背景。但作为一种解决方法,我在委托内部创建了人工 QTreeView 小部件,并带有一些定义良好的对象名称,在我的情况下为
DocumentTreeItems
:
TreeWidgetItemDelegate::TreeWidgetItemDelegate(QObject* parent)
: QStyledItemDelegate(parent)
{
artificial = new QTreeView(qobject_cast<QWidget*>(parent));
artificial->setObjectName("DocumentTreeItems");
artificial->setFixedSize(0, 0);
}
感谢我可以将样式附加到 qss 内的这个小部件:
#DocumentTree::item {
border: 1px solid transparent;
border-radius: 2px;
background-color: $primaryBackground;
&:hover {
border: 1px solid $contrastBorder;
background-color: $controlWidgetBackground;
}
&:selected {
border: 1px solid $accentBorder;
background-color: $accentBackground;
}
}
然后我可以使用样式重新绘制背景,并在委托的
paint
方法中引用我的人工小部件:
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, artificial);
这给出了预期的结果:
但是我对这个解决方案非常不满意,所以如果有人知道更好的解决方案,我会很高兴听到建议。