更改单个QTabWidget选项卡的颜色

时间:2019-01-07 07:52:10

标签: c++ qt qtabwidget

我想更改单个标签的颜色,请参见下面的屏幕截图。 FOO_SUP标签应该是红色的(现在只有按钮),其他所有标签都不应该。

Example

对于文本颜色,有bar->setTabTextColor(index, QColor(Qt::red)),但没有整个标签。设置标签小部件的标签样式表会更改所有标签的颜色。

我在这里找到了一种样式表来更改选项卡的颜色:https://stackoverflow.com/a/21687821/356726,但不能更改单个选项卡,我还需要能够在运行时确定选项卡是否为红色。

请明确说明,下面的小部件应保持黑色,标签仅显示红色。

1 个答案:

答案 0 :(得分:2)

一种选择是实现自己的标签栏(如here所述)。

无论如何,我发现代理样式的使用更加有用和简洁,因为它允许您部分覆盖绘画,而无需在标签栏上使用继承。它还将允许您轻松地将新样式应用于现有控件。

可能是这样的:

class TabBackgroundProxyStyle : public QProxyStyle {
public:
  TabBackgroundProxyStyle(const QString& base_style_name, const QMap<QString, QBrush>& backgrounds)
    : QProxyStyle(base_style_name),
      m_backgrounds(backgrounds) {
  }

  void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const override {
    if (element == CE_TabBarTab) {
      if (auto tab = qstyleoption_cast<const QStyleOptionTab*>(option)) {
        if (m_backgrounds.contains(tab->text)) {
          QStyleOptionTab opt(*tab);
          opt.palette.setBrush(QPalette::Background, m_backgrounds[tab->text]);
          return QProxyStyle::drawControl(element, &opt, painter, widget);
        }
      }
    }
    QProxyStyle::drawControl(element, option, painter, widget);
  }

private:
  const QMap<QString, QBrush> m_backgrounds;
};

要使用它,只需使用适当的选项卡颜色映射创建样式(使用C ++ 11的示例):

auto theTabWidget = new QTabWidget();
for (int ii = 0; ii < 10; ++ii) theTabWidget->addTab(new QWidget(), QString("Tab %1").arg(ii + 1));
const QMap<QString, QBrush> backgrounds = {
  {"Tab 2", QBrush(Qt::red)},
  {"Tab 3", QBrush("#c0b050")},
};
theTabWidget->tabBar()->setStyle(new TabBackgroundProxyStyle("", backgrounds));

如果您的用户界面允许该标签的文本在运行时进行更改(例如,即时翻译或该文本是文件名...),则必须相应地修改地图。

使用选项卡标签进行索引是因为样式选项不存储有关该选项卡的其他任何直接信息(甚至不存储关联的小部件,因为QTabBar仅负责呈现选项卡,因此不是容器)。

另一种选择是检查选项卡的矩形,对于只有几十个选项卡的选项卡栏来说,耗时不多,如果您不想处理标签,则功能更丰富:

class TabBackgroundProxyStyle : public QProxyStyle {
public:
  TabBackgroundProxyStyle(const QString& base_style_name, const QMap<int, QBrush>& backgrounds)
    : QProxyStyle(base_style_name),
      m_backgrounds(backgrounds) {
  }

  void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const override {
    if (element == CE_TabBarTab) {
      if (auto tab = qstyleoption_cast<const QStyleOptionTab*>(option)) {
        auto tabBar = qobject_cast<const QTabBar*>(widget);
        for (auto index : m_backgrounds.keys()) {
          if (tab->rect == tabBar->tabRect(index)) {
            QStyleOptionTab opt(*tab);
            opt.palette.setBrush(QPalette::Background, m_backgrounds[index]);
            return QProxyStyle::drawControl(element, &opt, painter, widget);
          }
        }
      }
    }
    QProxyStyle::drawControl(element, option, painter, widget);
  }

private:
  const QMap<int, QBrush> m_backgrounds;
};

使用:

auto theTabWidget = new QTabWidget();
for (int ii = 0; ii < 10; ++ii) theTabWidget->addTab(new QWidget(), QString("Tab %1").arg(ii + 1));
const QMap<int, QBrush> backgrounds = {
  {1, QBrush(Qt::red)},
  {4, QBrush("#c0b050")},
};
theTabWidget->tabBar()->setStyle(new TabBackgroundProxyStyle("", backgrounds));

可以从https://github.com/cbuchart/stackoverflow/tree/master/54070408-change-color-of-single-qtabwidget-tab下载完整的源代码


重要:此解决方案的主要缺点是与现有标签的样式表无法很好地结合:您必须禁用/注释QTabBar::tab的样式表才能能够应用样式。