更改单个 QTabWidget 选项卡的颜色

Posted

技术标签:

【中文标题】更改单个 QTabWidget 选项卡的颜色【英文标题】:Change color of single QTabWidget tab 【发布时间】:2019-01-07 07:52:10 【问题描述】:

我想改变单个标签的颜色,请看下面的截图。 FOO_SUPtab 应该是红色的(现在只有按钮是),其他的都不是。

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

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

为了清楚起见,下面的小部件应保持黑色,标签只有红色。

【问题讨论】:

我假设QTabWidget 使用QTabBar 来管理选项卡。 (QTabWidget on woboq.org) 因此,我查看了QTabBar::paintEvent() on woboq。因此,一个解决方案可能是重载QTabBar 并覆盖QTabBar::paintEvent(),根据您的意图调整绘画。 【参考方案1】:

一种选择是实现您自己的标签栏(如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/***/tree/master/54070408-change-color-of-single-qtabwidget-tab下载


重要提示:这个解决方案的主要缺点是它不能很好地与现有的选项卡样式表混合:您必须禁用/注释 QTabBar::tab 的样式表才能能够应用样式。

【讨论】:

以上是关于更改单个 QTabWidget 选项卡的颜色的主要内容,如果未能解决你的问题,请参考以下文章

更改 QTabWidget 中选定选项卡的光标

如何在 Pyside2 的 QTabWidget 中更改特定选项卡的字体?

访问 QTabWidget 中选项卡的小部件

在 QTabWidget 中查找选项卡的索引

Qt Python 访问 QTabWidget 中选项卡的内容

如何更改 TabLayout 选定选项卡的图标颜色?