PDA

View Full Version : Delegate doesn't paint properly



woodtluk
10th August 2010, 11:42
Hi everybody

I try to create my own delegate for a list view.
I'd like to draw my list items similar to the default behaviour. That is a picture on the left side and than a text. But the text is in html format to support some formation as different text size and text colour.

So I implemented my ouwn QStyledItemDelegate::paint method. But my items are not painted properly.
The first item is painted as supposed. But for the other items only the image is painted.
When I scroll the list view then sometimes other items are painted. But the text is drawn to far left and under the images.



void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
if(!index.isValid())
return;
painter->save();
// handle selection
if(option.state & QStyle::State_Selected){
painter->fillRect(option.rect, option.palette.color(QPalette::Highlight));
}
// get the oicture for the decoration role
QIcon ic = QIcon(qvariant_cast<QPixmap>(index.data(Qt::DecorationRole)));

QTextDocument doc;
QString txt = index.data(Qt::DisplayRole).toString();
doc.setHtml(txt);

// rectangle for the icon
QRect r = option.rect.adjusted(2, 2, -2, -2);
ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft);

// rectangle for the text
r = r.adjusted(60, 0, 0, 0);
doc.drawContents(painter, r);
painter->restore();
}


Any suggestions?

Thx Luke

Ginsengelf
10th August 2010, 15:36
Hi, check the values of r if they are what you expected.

Ginsengelf

ChiliPalmer
10th August 2010, 15:39
option.rect doesn't necessarily return the visible rect of the current index. You should try this:


QStyleOptionViewItemV4 opt = option;
QStyledItemDelegate::initStyleOption(&opt, index);
QRect rect = opt.rect;

From the Qt doc:

When reimplementing paint in a subclass. Use the initStyleOption() to set up the option in the same way as the QStyledItemDelegate; the option will always be an instance of QStyleOptionViewItemV4. Please see its class description for information on its contents.

Whenever possible, use the option while painting. Especially its rect variable to decide where to draw and its state to determine if it is enabled or selected.

woodtluk
10th August 2010, 16:53
Thanks for the hint.

It's still not working. But I'll try to toy around with the given code and read the docs.

woodtluk
11th August 2010, 11:43
Ok it's working now (more or less):


void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
if(!index.isValid())
return;

painter->save();
painter->setRenderHint(QPainter::Antialiasing);

QStyleOptionViewItemV4 opt = option;
QStyledItemDelegate::initStyleOption(&opt, index);
QRect rect = opt.rect;

// handle selection
if(option.state & QStyle::State_Selected){
painter->save();
QPen selectionPen(option.palette.color(QPalette::Highli ght));
selectionPen.setWidth(2);
painter->setPen(selectionPen);
painter->drawRoundedRect(rect.adjusted(1,1,-1,-1), 5, 5);
painter->restore();
}

QIcon ic = QIcon(qvariant_cast<QPixmap>(index.data(Qt::DecorationRole)));
rect = rect.adjusted(4, 4, -4, -4);
/// @todo if ic.isNull() ...
ic.paint(painter, rect, Qt::AlignVCenter|Qt::AlignLeft);

QTextDocument doc;
QAbstractTextDocumentLayout::PaintContext context;

QString txt = index.data(Qt::DisplayRole).toString();
doc.setHtml(txt);

// icon needs at most 60 pixels in y-axis
rect = rect.adjusted(62, 0, 0, 0);
doc.setPageSize(QSize(rect.width(), rect.height()));
painter->translate(rect.x(),rect.y());
doc.documentLayout()->draw(painter, context);

painter->restore();
}

Thaks for your help!
Cheers Luke