Thomas Kowalski
Thomas Kowalski

Reputation: 2184

Painting the background of a QTableView (with a custom QStyledItemDelegate)

I've been trying to use a "per-cell" custom background in a (custom) QTableView using a (custom) QStyledItemDelegate. Everything works well, until I actually try to have my custom background. Let's say for the sake of example, I want all my cells to have a red background. Here's the paint method of my 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);

How am I supposed to achieve that? I thought my way of doing it was rather simple and intuitive... What's wrong here?

Upvotes: 2

Views: 1504

Answers (2)

eyllanesc
eyllanesc

Reputation: 243983

Your code has the following errors:

Considering the above the solution is:

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

Upvotes: 5

Martin Hennings
Martin Hennings

Reputation: 16856

I know it's troublesome, but if you step through the source of QStyledItemDelegate::paint(), deep down inside you'll find some hard-coded values there (e.g. background color of selected items).

I ended up drawing over instead of under the QStyledItemDelegate::paint() with a semi-transparent painter / brush / image (after the base class call).

If the selection behavior isn't important to you, try performing the painting yourself before calling QStyledItemDelegate::paint() and see if that suits your needs.

Upvotes: 0

Related Questions