2013-01-10 21 views
7

Mam QTreeView i chcę różne kolory tła dla wierszy, w zależności od ich zawartości. Aby to osiągnąć, I pochodzi z class MyTreeView z QTreeView i wdrożył metodę malowania następująco:Zmiana koloru tła wiersza QTreeView nie działa

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

Początkowo ustawić setAlternatingRowColors(true); dla QTreeView.

Mój problem: Ustawianie koloru QPalette :: Base nie ma wpływu. Co drugi rząd pozostaje biały.

Jednak ustawienie QPalette :: AlternateBase działa zgodnie z oczekiwaniami. Próbowałem setAutoFillBackground(true) i setAutoFillBackground(false) bez żadnego efektu.

Czy są jakieś wskazówki, jak rozwiązać ten problem? Dziękuję Ci.


Uwagi: Ustawianie koloru poprzez dostosowanie MyModel::data(const QModelIndex&, int role) dla Qt::BackgroundRole nie daje pożądanego rezultatu. W takim przypadku kolor tła jest używany tylko dla części wiersza. Ale chcę pokolorować cały wiersz, w tym lewą stronę z rzeczami nawigacji drzewa.

Qt Wersja: 4.7.3


Aktualizacja: Z nieznanych powodów QPalette::Base wydaje się być nieprzezroczysta. setBrush tego nie zmienia. znalazłem następujące rozwiązania:

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

Odpowiedz

5

Zamiast podklasy QTreeView należy obsługiwać kolor tła za pośrednictwem modelu. Użyj funkcji data() i Qt::BackgroundRole do zmiany koloru tła wierszy.

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

że próbowała to, ale nie daje pożądanego efektu. Przy takim podejściu kolor tła nie jest malowany dla całego wiersza, ale tylko dla samych elementów drzewa. Tło nawigacji po drzewie (po lewej stronie elementów) nie ulega zmianie. – SebastianK

+0

@SebastianK Myślę, że to nadal jest właściwa droga, ale sposób w jaki zaimplementujesz 'warunek1' w tym przykładzie jest kluczem.Na przykład możesz zrobić 'if (index.sibling (index.row(), someColumnIndex) .data() == cokolwiek) {...}'. Musisz upewnić się, że nie jest to wymagane w przypadku, gdy 'index.column() == someColumnIndex' z nieskończonej rekurencji oczywiście. –

+0

@TimMeyer Próbowałem, że z 'condition1' beeing zawsze jest prawdziwe. Tło rzędu było tylko częściowo czerwone. W przypadku rozwiniętych elementów lewa część wiersza jest nadal biała. Przez "lewą część" rozumiem obszar z rzeczami nawigacji drzewa (rozwijanie/zwijanie [+]/[-] i linią do rodzica) – SebastianK

7

Jeśli jedynym problemem jest to, że Kielichowanie/Kontrola zwijanie nie mają tła jak reszta rzędu następnie użyć Qt::BackgroundRole w ::data() swojego modelu (opisanego przez pnezis w their answer) i dodać go do drzewa widok klasa:

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

Przetestowałem to na Windows (Vista i 7) przy użyciu Qt 4.8.0 i rozszerzenie/zwijanie strzałki mieć odpowiednie tło. Problem polega na tym, że strzałki te są częścią widoku i dlatego nie można ich obsługiwać w modelu.

+0

Dziękuję za odpowiedź. Jak powiedziałeś, wadą tego rozwiązania jest to, że jest on rozproszony między modelem a widokiem. Ale pomysł z 'fillRect' prowadzi mnie do rozsądnego obejścia. – SebastianK

+1

Zgadzam się, w tym przypadku może być lepiej mieć kolorowanie tylko w widoku - nadpisywanie innych funkcji członka drawXXX. Cieszę się że mogłem pomóc. –

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