Изменение цвета фона строки 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);
    }

person SebastianK    schedule 10.01.2013    source источник


Ответы (3)


Если единственная проблема заключается в том, что элементы управления расширением / свертыванием не имеют фона, как остальная часть строки, используйте Qt::BackgroundRole в ::data() вашей модели (как описано в 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);
}

Я тестировал это в Windows (Vista и 7), используя Qt 4.8.0, и стрелки развертывания / сворачивания имеют правильный фон. Проблема в том, что эти стрелки являются частью вида и поэтому не могут обрабатываться в модели.

person Wojciech Cierpucha    schedule 13.01.2013
comment
Спасибо за ваш ответ. Как вы сказали, недостатком этого решения является то, что оно разбросано между моделью и представлением. Но идея с fillRect привела меня к разумному обходному пути. - person SebastianK; 16.01.2013
comment
Я согласен, в этом случае может быть лучше иметь код окраски только в представлении - переопределение других функций-членов drawXXX. Я рад, что смог помочь. - person Wojciech Cierpucha; 16.01.2013

Вместо того, чтобы создавать подклассы QTreeView, вы должны обрабатывать цвет фона через вашу модель. Используйте функцию data() и _ 3_ для изменения цвета фона строк.

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();
}
person pnezis    schedule 10.01.2013
comment
Я пробовал это, но это не дает желаемого результата. При таком подходе цвет фона окрашивается не для всей строки, а только для самих элементов дерева. Фон древовидной навигации (в левой части элементов) не изменился. - person SebastianK; 10.01.2013
comment
@SebastianK Я думаю, что это по-прежнему правильный путь, но то, как вы реализуете condition1 в этом примере, является ключевым. Например, вы можете сделать if( index.sibling( index.row(), someColumnIndex ).data() == whatever ) { ... }. Вы должны убедиться, что это не вызывается в случае, когда index.column() == someColumnIndex, конечно, с бесконечной рекурсией. - person Tim Meyer; 10.01.2013
comment
@TimMeyer Я пробовал это с condition1 быть всегда верным. Фон ряда был лишь частично красным. Для развернутых элементов левая часть строки остается белой. Под левой частью я подразумеваю область с элементами навигации по дереву (разворачивание / сворачивание [+] / [-] и родительская строка) - person SebastianK; 10.01.2013

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());
}
person atz    schedule 17.03.2017