Рисование фона QTableView (с пользовательским QStyledItemDelegate)

Я пытался использовать настраиваемый фон для каждой ячейки в (настраиваемом) QTableView с помощью (настраиваемого) QStyledItemDelegate. Все работает хорошо, пока я не попытаюсь установить свой собственный фон. Скажем, для примера, я хочу, чтобы все мои ячейки имели красный фон. Вот paint метод моего Delegate.

    QStyleOptionViewItem newOption = option;
    auto normalText = newOption.palette.brush(QPalette::ColorGroup::Normal, QPalette::ColorRole::Text);
    // Works as expected
    newOption.palette.setBrush(QPalette::ColorGroup::Normal, QPalette::ColorRole::Highlight, Qt::gray); // QBrush(Qt::GlobalColor::blue, Qt::BrushStyle::NoBrush));
    // Expected too: selected cells are gray
    newOption.palette.setBrush(QPalette::ColorGroup::Normal, QPalette::ColorRole::HighlightedText, normalText);

    // All of the following do NOT work. I've tried every possible combination without success.
    newOption.palette.setBrush(QPalette::ColorGroup::Normal, QPalette::ColorRole::Window, Qt::red);
    newOption.palette.setBrush(QPalette::ColorGroup::Inactive, QPalette::ColorRole::Base, Qt::red);
    newOption.palette.setBrush(QPalette::ColorGroup::Inactive, QPalette::ColorRole::AlternateBase, Qt::red);
    newOption.palette.setBrush(QPalette::ColorGroup::Active, QPalette::ColorRole::Base, Qt::red);
    newOption.palette.setBrush(QPalette::ColorGroup::Active, QPalette::ColorRole::AlternateBase, Qt::red);
    QStyledItemDelegate::paint(painter, newOption, index);

Как я должен этого добиться? Я думал, что мой способ сделать это был довольно простым и интуитивным... Что здесь не так?

Более простой подход — это обработка роли Qt::BackgroundRole в модели вашей таблицы.

vahancho 24.06.2019 13:48

У меня две проблемы с использованием data и BackgroundRole. Первый заключается в том, что его использование подразумевает, что фоновый цвет ячейки является каким-то данные из модели, а это не так. Кроме того, позже я захочу иметь собственный рисунок границы для определенных ячеек, и я не смогу сделать это в data, используя BackgroundRole, как вы предлагаете. Поэтому я предпочитаю хранить все это здесь, в delegatepaint.

Thomas Kowalski 24.06.2019 13:50
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
621
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я знаю, что это хлопотно, но если вы перейдете к источнику QStyledItemDelegate::paint(), глубоко внутри вы найдете некоторые жестко запрограммированные значения (например, цвет фона выбранных элементов).

В итоге я нарисовал над вместо подQStyledItemDelegate::paint() полупрозрачным художником/кистью/изображением (после вызова базового класса).

Если поведение выбора для вас не важно, попробуйте выполнить рисование самостоятельно до, вызвав QStyledItemDelegate::paint(), и посмотрите, подходит ли оно вам.

Вы имеете в виду сначала вызвать QStyledItemDelegate::paint и только после звонка, что мне нужно сделать? Что мне не нравится, так это то, что мне придется рисовать что-то самому, и я боюсь, что это было бы лучше, если бы Qt делал это сам. Разве нет другого пути?

Thomas Kowalski 24.06.2019 15:36
Ответ принят как подходящий

В вашем коде есть следующие ошибки:

  • Не используйте метод paint(), если вы хотите настроить свойства QStyleOptionViewItem, так как внутри метода paint() он будет перезаписан методом initStyleOption(), который вызывается внутри.

  • Не все свойства картины получены из QPalette, в случае цвета фона необходимо использовать свойство backgroundBrush.

Учитывая вышеизложенное решение:

#include <QtWidgets>

class StyledItemDelegate: public QStyledItemDelegate
{
public:
    using QStyledItemDelegate::QStyledItemDelegate;
protected:
    void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override
    {
        QStyledItemDelegate::initStyleOption(option, index);
        QBrush normalText = option->palette.brush(QPalette::ColorGroup::Normal, QPalette::ColorRole::Text);
        option->palette.setBrush(QPalette::ColorGroup::Normal, QPalette::ColorRole::Highlight, Qt::gray);
        option->palette.setBrush(QPalette::ColorGroup::Normal, QPalette::ColorRole::HighlightedText, normalText);
        option->backgroundBrush = QColor(Qt::red);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QTableView w;
    StyledItemDelegate *delegate = new StyledItemDelegate(&w);
    w.setItemDelegate(delegate);
    QStandardItemModel model(10, 10);
    w.setModel(&model);
    w.show();

    return a.exec();
}

Другие вопросы по теме