HowTo draw different backgrounds with QStyledItemDelegate?
-
11-06-2021 - |
Domanda
Problem:
- I have
QTreeView
object, and aQStandardItemModel
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, BUTQStandardItem
doesn't havesetProperty
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 reimplementpaint
method, BUT I can't just change background, becauseQStyledItemDelegate::paint( painter, opt, index );
code will overdraw mydrawPixmap
...
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...
Soluzione
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:
Have a nice day! :)
PS: no need redrawing icons, text, selection...
Altri suggerimenti
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.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow