Set QItemDelegate on a particular QTreeWidgetItem

2.3k views Asked by At

Is it possible to set a QItemDelegate on a particular QTreeWidgetItem? I need to color some of the QTreeWidgetItems with a particular color.

I assume it is possible as we have QAbstractItemView::setItemDelegateForRow but I can't figure out how. I can't use QAbstractItemView::setItemDelegateForRow because I need to set a custom delegate on a child row inside the QTreeWidget.

Does anyone know a solution for that?

4

There are 4 answers

3
Bowdzone On BEST ANSWER

You can access the QTreeWidget from you delegate's paint routine to check if a condition for painting the background is met

void custom_delegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    const QTreeWidget* tree_widget = qobject_cast<const QTreeWidget*>(qstyleoption_cast<const QStyleOptionViewItemV3*>(&option)->widget);
    ....
}

or you store something in the QModelIndex UserData as Chernobyl suggested. In that case I would however create an enum for flags (if this is applicable in your case):

enum custom_painter_flags{
    paint_default = 0,
    paint_background = 1
};

void somewhere_creating_the_items()
{
    QTreeWidgetItem* newitem = new QTreeWidgetItem(...);
    newitem->setData(0, Qt::UserRole, QVariant::fromValue<int>(custom_painter_flags::paint_background));
}

void custom_delegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    custom_painter_flags painter_flags = static_cast<painter>(index.data(Qt::UserRole).value<int>());

    if(painter_flags & paint_background){
        ....
    }
}

Unfortunately I have not much time right now so this is thrown together pretty quick. Feel free to edit if you find any errors.

1
KarNal On

You can use qss on the QTreeWidgetItem to change color or background color.

1
KarNal On

I have done it for a QTableWidget, You must check the value of all your QTreeWidgetItem and set a background color / color.

For example, for my QTableWidget i have done something like this in a loop :

if(good item): MyQTableItem.setBackground(QtGui.QColor(255,255,255))

5
Jablonski On

You can't use QTreeWidgetItem in delegate directly (probably you can store list of this items inside delegates but I think that it is not efficient), because delegates works with QModelIndex and data inside different roles. You can set data to Qt::UserRole+1 and access it inside delegate. For example:

QTreeWidgetItem *cities = new QTreeWidgetItem(ui->treeWidget);
//...
cities->setData(0,Qt::UserRole+1,"chosen one");

QTreeWidgetItem *osloItem = new QTreeWidgetItem(cities);
//...

QTreeWidgetItem *berlinItem = new QTreeWidgetItem(cities);
//...
berlinItem->setData(0,Qt::UserRole+1,"chosen one");

Inside delegate (just example):

    void ItemDelegatePaint::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QString txt = index.model()->data( index, Qt::DisplayRole ).toString();

    if( option.state & QStyle::State_Selected )
    {
        if(index.data(Qt::UserRole+1).toString() == "chosen one")
            painter->fillRect( option.rect,Qt::green );
        else
            painter->fillRect( option.rect, option.palette.highlight() );
    }else
    if(option.state & QStyle::State_MouseOver)
    {
        if(index.data(Qt::UserRole+1).toString() == "chosen one")
            painter->fillRect( option.rect,Qt::yellow );
        else
            painter->fillRect( option.rect, Qt::transparent );
    }
    else
    {
        QStyledItemDelegate::paint(painter,option,index);
    }
}