【问题标题】:Changing the row background color of a QTreeView does not work更改 QTreeView 的行背景颜色不起作用
【发布时间】:2012-12-24 16:20:50
【问题描述】:

我有一个QTreeView 并希望行的背景颜色不同,具体取决于它们的内容。为了实现这一点,我从QTreeView派生了一个class MyTreeView,并实现了paint方法如下:

    void MyTreeView::drawRow (QPainter* painter,
                              const QStyleOptionViewItem& option,
                              const QModelIndex& index) const
    {
      QStyleOptionViewItem newOption(option);

      if (someCondition)
      {
        newOption.palette.setColor( QPalette::Base, QColor(255, 0, 0) );
        newOption.palette.setColor( QPalette::AlternateBase, QColor(200, 0, 0) );
      }
      else
      {
        newOption.palette.setColor( QPalette::Base, QColor(0, 0, 255) );
        newOption.palette.setColor( QPalette::AlternateBase, QColor(0, 0, 200) );
      }

      QTreeView::drawRow(painter, newOption, index);
    }

最初,我为 QTreeView 设置了setAlternatingRowColors(true);

我的问题:QPalette::Base 设置颜色无效。每隔一行保持白色。

但是,设置 QPalette::AlternateBase 可以正常工作。 我试过setAutoFillBackground(true)setAutoFillBackground(false)没有任何效果。

是否有任何提示如何解决这个问题?谢谢。


备注:通过将MyModel::data(const QModelIndex&, int role) 调整为Qt::BackgroundRole 来设置颜色并不能提供所需的结果。在这种情况下,背景颜色仅用于行的一部分。但我想为整行着色,包括左侧带有树导航的东西。

Qt 版本: 4.7.3


更新: 由于未知原因,QPalette::Base 似乎是不透明的。 setBrush 不会改变这一点。 我找到了以下解决方法:

    if (someCondition)
    {
        painter->fillRect(option.rect, Qt::red);
        newOption.palette.setBrush( QPalette::AlternateBase, Qt::green);
    }
    else
    {
        painter->fillRect(option.rect, Qt::orange);
        newOption.palette.setBrush( QPalette::AlternateBase, Qt:blue);
    }

【问题讨论】:

    标签: c++ qt user-interface qtreeview


    【解决方案1】:

    如果唯一的问题是展开/折叠控件没有像行的其余部分那样的背景,则在模型的::data() 中使用Qt::BackgroundRole(如their answer 中的pnezis 所述)并添加这个到你的树视图类:

    void MyTreeView::drawBranches(QPainter* painter,
                                  const QRect& rect,
                                  const QModelIndex& index) const
    {
      if (some condition depending on index)
        painter->fillRect(rect, Qt::red);
      else
        painter->fillRect(rect, Qt::green);
    
      QTreeView::drawBranches(painter, rect, index);
    }
    

    我已经使用 Qt 4.8.0 在 Windows(Vista 和 7)上对此进行了测试,并且展开/折叠箭头具有适当的背景。问题是这些箭头是视图的一部分,因此无法在模型中处理。

    【讨论】:

    • 感谢您的回答。正如您所说,这种解决方案的缺点是它分散在模型和视图之间。但是fillRect 的想法让我找到了一个合理的解决方法。
    • 我同意,在这种情况下,最好只在视图中使用着色代码 - 覆盖其他 drawXXX 成员函数。我很高兴能帮上忙。
    【解决方案2】:

    您应该通过模型处理背景颜色,而不是继承 QTreeView。使用data() 函数和Qt::BackgroundRole 更改行的背景颜色。

    QVariant MyModel::data(const QModelIndex &index, int role) const
    {
       if (!index.isValid())
          return QVariant();
    
       if (role == Qt::BackgroundRole)
       {
           if (condition1)
              return QColor(Qt::red);
           else
              return QColor(Qt::green); 
       }
    
       // Handle other roles
    
       return QVariant();
    }
    

    【讨论】:

    • 我试过这个,但这并没有产生预期的结果。使用这种方法,不会为整行绘制背景颜色,而只是为树项本身绘制背景颜色。树导航的背景(在项目的左侧)没有改变。
    • @SebastianK 我认为这仍然是正确的方法,但在此示例中实现condition1 的方式是关键。例如,您可以使用if( index.sibling( index.row(), someColumnIndex ).data() == whatever ) { ... }。当然,您必须确保在 index.column() == someColumnIndex 无限递归的情况下不会调用它。
    • @TimMeyer 我尝试了condition1beeing 总是正确的。该行的背景只有部分红色。对于展开的项目,行的左边部分仍然是白色的。 “左侧”是指带有树导航内容的区域(展开/折叠 [+]/[-] 和父行)
    【解决方案3】:

    https://www.linux.org.ru/forum/development/4702439

    if ( const QStyleOptionViewItemV4* opt = qstyleoption_cast<const QStyleOptionViewItemV4*>(&option) )
    {
            if (opt.features & QStyleOptionViewItemV4::Alternate)
                painter->fillRect(option.rect,option.palette.alternateBase());
            else
                painter->fillRect(option.rect,painter->background());
    }
    

    【讨论】:

      猜你喜欢
      • 2014-04-09
      • 1970-01-01
      • 2016-11-28
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      相关资源
      最近更新 更多