每列

时间:2017-06-01 09:24:44

标签: c++ qt stylesheet qheaderview

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

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

但是,我想分别编辑列标题。我在documentation上发现我们可以使用::first::last ...

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

2 个答案:

答案 0 :(得分:2)

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

要解决此问题,您基本上可以使用重新实现其QHeaderView的自定义paintEvent,或者我建议您使用的选项:使用自定义样式(QProxyStyle是一个很好的选择,因为它允许您只实现您想要的功能,并从 base 样式继承其余功能。您必须专门为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);
    }
  }
};

注意:我设法让它只使用 fusion 样式。似乎 windows 样式实现了它自己的标题颜色方案。如果你想使用这样的风格,你应该手动绘制标题(在同一个drawControl内,没有必要重新实现QHeaderView)。

仅使用自定义样式qApp->setStyle(new MyProxyStyle("fusion"));(将 fusion 作为基本样式)。

<强>结果

header

非常重要的注意事项:您必须注意,as indicated in the documentation无法同时使用自定义QStyle和样式表又:

  

警告:自定义QStyle子类当前不支持Qt样式表。我们计划在将来的某个版本中解决此问题。

上一个回答

我错误地回答了QTabBar问题的问题,这个问题恰好非常相似:除了一些预先定义的选项卡(第一个或最后一个)之外,不可能使用样式表来配置给定选项卡, 例如)。我们必须重新实现QTabBar或使用自定义样式(如前所述)。我正在为它保留解决方案,以防它对其他人有用。

棘手的部分是样式选项没有关于选项卡索引的任何信息,所以你必须以某种方式解决它。我发现使用选项卡的x位置(可从选项和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);
    }
  }
};

设置画笔时使用不同颜色角色背后的原因来自于绘制节时不同的样式使用不同的角色( fusion 样式使用QPalette::Button作为背景,而 > windows 使用QPalette::Background代替)。例如,其他角色可以调整边框和文本颜色。

<强>结果

使用 fusion 样式:

fusion

使用 windows 样式:

windows

答案 1 :(得分:0)

在一些简单的情况下,您可以使用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);