我正在尝试编辑QTreeWidget
.
我发现我可以在QHeaderView::section
那里编辑它,编辑背景、颜色、边框......
但是,我想单独编辑列标题。我在我们可以使用的文档::first
中找到,::last
...
有没有办法精确地指定另一个部分([index = 3]
例如)?
我正在尝试编辑QTreeWidget
.
我发现我可以在QHeaderView::section
那里编辑它,编辑背景、颜色、边框......
但是,我想单独编辑列标题。我在我们可以使用的文档::first
中找到,::last
...
有没有办法精确地指定另一个部分([index = 3]
例如)?
::first
不,除了使用, ::last
,之外,没有其他方法可以使用样式表来改变标题部分的外观::middle
。QStylesheetStyle
(加载样式表时使用的那个)仅实现这些状态。
要解决它,您基本上可以使用自定义QHeaderView
重新实现其其余的来自基本样式)。您必须专门为该元素重新实现该方法:paintEvent
QProxyStyle
drawControl
CE_Header
virtual void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const override {
if (element == CE_Header) { // sections
// ...
} else { // default behaviour for anything else
QProxyStyle::drawControl(element, option, painter, widget);
}
}
现在,该QStyleOptionHeader::section
变量包含正在绘制的部分的索引,因此您可以使用它来计算颜色。
最小代理样式的完整代码是:
class MyProxyStyle : public QProxyStyle {
public:
MyProxyStyle(const QString& name) : // "fusion", "windows", ...
QProxyStyle(name) {
}
virtual void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const override {
if (element == CE_Header) {
auto ho = *qstyleoption_cast<const QStyleOptionHeader*>(option);
auto headerView = qobject_cast<const QHeaderView*>(widget);
ho.text = QString::number(ho.section); // for testing, it prints the section index
auto pal = ho.palette;
const QColor color(ho.section * 32 + 64, 0, 0); // color based on index
pal.setBrush(QPalette::All, QPalette::Button, color);
ho.palette = pal;
QProxyStyle::drawControl(element, &ho, painter, widget);
} else {
QProxyStyle::drawControl(element, option, painter, widget);
}
}
};
注意:我已经设法让它只与融合风格一起工作。似乎windows样式实现了它自己的标题配色方案。如果你想使用这样的样式,那么你应该手动绘制标题(在同一个drawControl
中,没有必要重新实现QHeaderView
)。
仅使用自定义样式qApp->setStyle(new MyProxyStyle("fusion"));
(以融合为基本样式)。
结果
非常重要的注意事项:您必须知道,如文档中所述,您不能同时使用自定义QStyle
和样式表:
警告:自定义 QStyle 子类目前不支持 Qt 样式表。我们计划在未来的某个版本中解决这个问题。
上一个答案
错误地,我之前回答了问题的QTabBar
问题,这恰好非常相似:除了一些预定义的选项卡(例如,第一个或最后一个)之外,不可能使用样式表来配置给定的选项卡。我们必须重新实现QTabBar
或使用自定义样式(如前所述)。我保留它的解决方案,以防它对其他人有用。
棘手的部分是样式选项没有关于标签索引的任何信息,因此您必须以某种方式弄清楚。我发现使用x
选项卡的位置(可从 option 和 访问QTabBar
)是匹配选项卡的有效指示器。如果你的标签栏是垂直渲染的,你应该使用y
坐标,如果标签栏是多行的,那么使用整个rect
.
最小代理样式的完整代码是:
class MyProxyStyle : public QProxyStyle {
public:
MyProxyStyle(const QString& name) : // "fusion", "windows", ...
QProxyStyle(name) {
}
virtual void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const override {
if (element == CE_TabBarTab) {
auto to = *qstyleoption_cast<const QStyleOptionTab*>(option);
auto tabBar = qobject_cast<const QTabBar*>(widget);
for (int ii = 0; ii < tabBar->count(); ++ii) { // must find manually the tab
const auto rect = tabBar->tabRect(ii);
if (rect.x() == to.rect.x()) { // found the index of tab being painted
to.text = QString::number(ii); // for testing, it prints the tab index
auto pal = to.palette;
const QColor color(ii * 32 + 64, 0, 0); // color based on index
pal.setBrush(QPalette::All, QPalette::Button, color);
pal.setBrush(QPalette::All, QPalette::Background, color);
to.palette = pal;
break;
}
}
QProxyStyle::drawControl(element, &to, painter, widget);
} else {
QProxyStyle::drawControl(element, option, painter, widget);
}
}
};
设置画笔时使用不同颜色角色的原因是因为不同的风格在绘制截面时使用不同的角色(融合风格QPalette::Button
用于背景,而windows使用QPalette::Background
代替)。例如,其他角色将允许您调整边框和文本颜色。
结果
融合风格:
带windows风格:
在一些简单的情况下,您可以使用 QAbstractItemModel 和角色的方法来更改 QHeaderView 的部分颜色:
// text of 0-section will be red in header
m_model.setHeaderData(0, Qt::Horizontal, QBrush(Qt::red), Qt::ForegroundRole);
// background of a 25-section will be blue in header
m_model.setHeaderData(25, Qt::Horizontal, QBrush(Qt::blue), Qt::BackgroundRole);