[Interest] Item / Views: QLabel delegate

Volker Hilsheimer volker.hilsheimer at qt.io
Mon Dec 4 15:34:58 CET 2023


Hi László,

On 2 Dec 2023, at 07:39, Tony Rietwyk <tony at rightsoft.com.au> wrote:
On 2/12/2023 12:06 am, Laszlo Papp wrote:
Hi everyone,

I am not able to render a custom widget, like a QLabel in a QTreeView cell with a custom delegate. The delegate code is this:


[…]


But I am seeing my QTreeView cell empty instead of seeing the above "This a test message" in there. Do you know what I may be doing wrong?

I took this idea from here:
https://groups.google.com/g/python_inside_maya/c/FXB_V0llUpY/m/mpJOQkyJCgAJ


This is not only quite expensive (depending on how many delegates you plan to instantiate), you are also making a lot of assumptions about what the widget is doing. Ie. does the widget have a meaningful size? Has it laid out its content while it’s not visible (many widgets postpone heavy work until they get polished, just before being shown)? You can't know any of this, and even if things might happen to work with some widgets (or if you manage to make them work by some explicit event posting or processing) you shouldn’t rely on these behaviours. They are often implementation details and might change from one Qt version to the next.

In short: don’t use widgets as an off-screen component to render stuff.

What Justin on the Google group is suggesting as the first option, and what Tony is doing in his snippet below, is the correct way: use the QStyle API and QTextDocument to draw the various elements, and to calculate size requirements and such.


Hi Laslo,

In my delegate, I use a QTextDocument instead and I also override sizeHint:

void MessagesDelegate::paint(
        QPainter *painter,
        const QStyleOptionViewItem &option,
        const QModelIndex &index) const
{
 QStyleOptionViewItem optionV4 = option;
 initStyleOption(&optionV4, index);
 QStyle *style = optionV4.widget ? optionV4.widget->style() : QApplication::style();
 QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &optionV4);
 // Draw the item without any text:
 style->drawPrimitive(QStyle::PE_PanelItemViewItem, &optionV4, painter, optionV4.widget);
 _doc.setTextWidth(-1);
 _doc.setHtml("This is a test message");
 QAbstractTextDocumentLayout::PaintContext ctx;
 ctx.palette = optionV4.palette;
 // TODO:  Change ctx.palette according to cell being disabled and/or selected.
 painter->save();
 painter->translate(textRect.topLeft());
 painter->setClipRect(textRect.translated(-textRect.topLeft()));
 doc.documentLayout()->draw(painter, ctx);
 painter->restore();
}


QSize MessagesDelegate::sizeHint(
        const QStyleOptionViewItem& option,
        const QModelIndex& index) const
{
 _doc.setTextWidth(-1);
 _doc.setHtml("This is a test message");
 return QSize(_doc.idealWidth(), _doc.size().height());
}


Sorry I can't release the full code as it does lots of other things like icon decoration role, clicking on links in the HTML, etc.

Hope that helps,

Tony


Best regards,

Volker

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20231204/b535cbf4/attachment.htm>


More information about the Interest mailing list