2013-01-10 77 views
7

我有一个QTreeView,并且需要不同的行背景颜色,具体取决于它们的内容。为了实现这一点,我衍生自QTreeView一个class MyTreeView和如下实施的涂料方法:更改QTreeView的行背景颜色不起作用

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

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

我的问题:设置颜色为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); 
    } 

回答

5

相反子类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(); 
} 
+1

我想这一点,但是这并不能产生预期的结果。采用这种方法,背景颜色不会涂满整行,而只能涂抹树项目本身。树导航的背景(在项目的左侧)没有改变。 – SebastianK

+0

@SebastianK我认为这仍然是正确的方法,但是在这个例子中实现'condition1'的方式是关键。例如,你可以做'if(index.sibling(index.row(),someColumnIndex).data()== whatever){...}'。当然,你必须确保这个函数没有被调用到'index.column()== someColumnIndex'的情况。 –

+0

@TimMeyer我试着用'condition1'来保证总是真的。该行的背景仅部分呈红色。对于扩展项目,行的左侧部分仍然是白色。对于“左边部分”,我指的是具有树形导航内容的区域(扩展/折叠[+]/[ - ]和父行) – SebastianK

7

如果唯一的问题是,扩张/折叠控件没有像该行的其余部分的背景,然后在你的模型(如通过their answerpnezis描述)的::data()使用Qt::BackgroundRole,并添加到您的树视图类:

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和Windows 7)/折叠箭头有适当的背景。问题是这些箭头是视图的一部分,因此无法在模型中处理。

+0

谢谢您的回答。正如你所说,这个解决方案的缺点是它分散在Model和View之间。但是'fillRect'的想法让我有一个合理的解决方法。 – SebastianK

+1

我同意,在这种情况下,只在视图中使用着色代码可能会更好 - 覆盖其他drawXXX成员函数。我很高兴能够提供帮助。 –

0

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