Search code examples
qtqt4qstyleditemdelegate

HowTo draw different backgrounds with QStyledItemDelegate?


Problem:

  • I have QTreeView object, and a QStandardItemModel as model to view widget;
  • For some item's I have set data with setData method to split them with a parameter;
  • So I need to draw different background pixmap for QStandardItem items, which are with icon's and some text data;
  • And don't want to redraw all the items objects, I mean icon and text. Just change background.

First, I was thinking that:

  • I could set CSS stylesheets in Qt Designer for the object with 2 different background pictures, BUT QStandardItem doesn't have setProperty method...

Example:

QTreeView#treeView::item[ROLE="AAA"],
QTreeView#treeView::branch[ROLE="AAA"]
{
    height: 25px;
    border: none;
    color: #564f5b;
    background-image: url(:/backgrounds/images/row1.png);
    background-position: top left;
}

QTreeView#treeView::item[ROLE="BBB"],
QTreeView#treeView::branch[ROLE="BBB"]
{
    height: 25px;
    border: none;
    color: #564f5b;
    background-image: url(:/backgrounds/images/row2.png);
    background-position: top left;
}
  • then I created my own delegate, inherited from QStyledItemDelegate class, and reimplement paint method, BUT I can't just change background, because QStyledItemDelegate::paint( painter, opt, index ); code will overdraw my drawPixmap...

Example:

QStyleOptionViewItemV4 opt = option; // Для обхода QTBUG-4310
opt.state &= ~QStyle::State_HasFocus; // Чтобы не рисовался прямоугольник фокуса 

QStyledItemDelegate::paint( painter, opt, index );    

// HERE I WANT TO CHANGE BACKGROUND (DEFAULT IS ALREADY SET IN DESIGNER WITH ABOVE CODE)
if( index.data( SORT_ROLE ).toBool() )
{
    const QPixmap pixmap( ":/backgrounds/images/backgrounds/contractor_row__high_priority.png" );
    painter->drawPixmap( option.rect, pixmap, pixmap.rect() );

    QStyledItemDelegate::paint( painter, opt, index );
}

So I'm stuck...


Solution

  • Here is my trick:

    The Designer's stylesheet part:

    QTreeView#treeView
    {
        border: none;
        background-color:#f0f0f1;
    }   
    
    QTreeView#treeView::item,
    QTreeView#treeView::branch
    {
        height: 25px;
        border: none;
        color: #564f5b;
    }
    
    QTreeView#treeView::item:selected,
    QTreeView#treeView::branch:selected
    {
        border-bottom: none;
        color: #ffffff;    
        background-image: url(:/backgrounds/images/backgrounds/kontragents_row_selection.png);
        background-position: top left;  
    
    }
    
    QTreeView#treeView::item:selected:!active,
    QTreeView#treeView::branch:selected:!active
    {
        color: #ffffff;
    }
    

    Delegate reimplemented paint() method:

    void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
     {
          QStyleOptionViewItemV4 opt = option; // Для обхода QTBUG-4310
          opt.state &= ~QStyle::State_HasFocus; // Чтобы не рисовался прямоугольник фокуса
    
          QBrush brush = opt.backgroundBrush;
          brush.setTexture( QPixmap( index.data( SORT_ROLE ).toBool()
               ? BACKGROUND_HIGH_PRIORITY
               : BACKGROUND_STANDARD ) );
    
          // FILL BACKGROUND     
          painter->save();
          painter->fillRect( opt.rect, brush );
          painter->restore();
    
          // DRAW ICON & TEXT
          QStyledItemDelegate::paint( painter, opt, index );
    
          // IF ( CHILD ) THEN PAINT OVER ONLY! BRANCH RECT
          bool isIndexParent = !index.parent().isValid();
          if( !isIndexParent )
          {
               QRect rect( 0, opt.rect.y(), 20, opt.rect.height() );
    
               if( opt.state & QStyle::State_Selected )
               {
                    brush.setTexture( QPixmap( BACKGROUND_SELECTED ) );
               }
    
               painter->save();
               painter->fillRect( rect, brush );
               painter->restore();
          }
     }
    

    Resulting QTreeView view:

    enter image description here

    Have a nice day! :)

    PS: no need redrawing icons, text, selection...