2013-01-10 124 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()); 
}