Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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...

like image 821
mosg Avatar asked Jan 27 '26 07:01

mosg


2 Answers

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...

like image 108
mosg Avatar answered Jan 29 '26 11:01

mosg


The delegate's paint method is all or nothing, so you won't be able to mix your background with the default implementation's.

However, if you're competent enough to even consider writing a custom delegate, you should have no problem implementing one that can draw your background plus icon and text.

like image 36
cmannett85 Avatar answered Jan 29 '26 12:01

cmannett85



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!