QHeaderView 样式每列

QHeaderView style each column

我正在尝试编辑 QTreeWidget 的 header 的样式。

我发现我可以使用 QHeaderView::section 编辑它,然后编辑背景、颜色、边框...

不过,我想单独编辑 header 列。我在 documentation 上发现我们可以使用 ::first::last...

有没有办法精确指定另一个部分(例如 [index = 3])?

不,除了使用 ::first::last::middle 之外,无法使用样式表更改 header 部分的外观。 QStylesheetStyle(加载样式表时使用的)仅实现这些状态。

要解决它,您基本上可以使用 re-implements 其 paintEvent 的自定义 QHeaderView,或者,我推荐您的选项:使用自定义样式(QProxyStyle 是一个不错的选择,因为它允许您仅实现所需的功能并从 base 样式继承其余功能)。您必须 re-implement 专门针对 CE_Header 元素的 drawControl 方法:

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);
    }
  }
};

注意:我设法让它只与 fusion 风格一起工作。 windows 样式似乎为 header 实现了它自己的配色方案。如果你想使用这样的风格,那么你应该手动绘制header(在相同的drawControl中,不需要re-implement和QHeaderView)。

要使用自定义样式只需 qApp->setStyle(new MyProxyStyle("fusion"));(以 fusion 作为基本样式)。

结果


非常重要的注意事项:您必须知道,as indicated in the documentation,您不能使用自定义 QStyle 和样式表同时存在:

Warning: Qt style sheets are currently not supported for custom QStyle subclasses. We plan to address this in some future release.


上一个回答

之前我错误地回答了 QTabBar 问题,这恰好非常相似:除了某些 pre-defined 之外,无法使用样式表来配置给定的选项卡(例如,第一个或最后一个)。我们必须 re-implement QTabBar 或使用自定义样式(和以前一样)。我保留了它的解决方案,以防它对其他人有用。

棘手的部分是样式选项没有任何关于选项卡索引的信息,因此您必须以某种方式弄清楚它。我发现使用选项卡的 x 位置(可从选项和 QTabBar 访问)是匹配选项卡的有效指标。如果你的标签栏是垂直呈现的,你应该使用 y 坐标,如果标签栏是 multi-line,那么使用整个 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);
    }
  }
};

设置笔刷时使用不同颜色角色的原因是因为不同风格在绘制部分时使用不同角色(fusion风格使用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);