Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to draw styled text in QStyledItemDelegate



  • Hi,

    I need to reimplement QStyledItemDelegate's paint method due to specific reasons of drawing different item parts based on index data, which may affect decoration and text rectangle position, but with ability of using stylesheet if itemDataRoles are not set.

    Everything is working well, due to using QStyleCommon's drawPrimitive in most of cases. But the text field and it's colors seems to be impossible to implement for me. QPalette stored in option or in QTreeView widget (stored in option.widget) does not include style colors for the item. Is there way how to "get palette for QTreeView item?" or "draw styled text with entering text value, rectangle and states?".

    Thanks for reading, happy for answer.



  • You can just use QStyle::drawItemText. Below I show 2 examples, one just fixes the text and uses drawControl, the other manually writes the text using drawItemText (ignore the sizeHint implementations)

    #include <QApplication>
    #include <QStyledItemDelegate>
    #include <QStandardItemModel>
    #include <QStylePainter>
    #include <QListView>
    #include <QFontMetrics>
    
    class FixTextDelegate : public QStyledItemDelegate{
        Q_DISABLE_COPY(FixTextDelegate)
    public:
        using QStyledItemDelegate::QStyledItemDelegate;
        void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
        {
            Q_ASSERT(index.isValid());
            QStyleOptionViewItem opt = option;
            initStyleOption(&opt, index);
            opt.text = opt.text + QChar(' ') + index.data(Qt::UserRole).toString();
            const QWidget *widget = option.widget;
            QStyle *style = widget ? widget->style() : QApplication::style();
            style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
        }
        QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
        {
            QVariant value = index.data(Qt::SizeHintRole);
            if (value.isValid())
                return qvariant_cast<QSize>(value);
            QStyleOptionViewItem opt = option;
            initStyleOption(&opt, index);
            opt.text = opt.text + QChar(' ') + index.data(Qt::UserRole).toString();
            const QWidget *widget = option.widget;
            QStyle *style = widget ? widget->style() : QApplication::style();
            return style->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), widget);
        }
    };
    
    class ManualTextDelegate : public QStyledItemDelegate{
        Q_DISABLE_COPY(ManualTextDelegate)
    public:
        using QStyledItemDelegate::QStyledItemDelegate;
        void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
        {
            Q_ASSERT(index.isValid());
            QStyleOptionViewItem opt = option;
            initStyleOption(&opt, index);
            opt.text.clear();
            const QWidget *widget = option.widget;
            QStyle *style = widget ? widget->style() : QApplication::style();
            style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
            opt.text = index.data().toString() + QChar(' ') + index.data(Qt::UserRole).toString();
            style->drawItemText(painter,opt.rect,Qt::AlignCenter,opt.palette,opt.state & QStyle::State_Enabled,opt.text);
        }
        QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
        {
            QVariant value = index.data(Qt::SizeHintRole);
            if (value.isValid())
                return qvariant_cast<QSize>(value);
            QStyleOptionViewItem opt = option;
            initStyleOption(&opt, index);
            opt.text = opt.text + QChar(' ') + index.data(Qt::UserRole).toString();
            const QWidget *widget = option.widget;
            QStyle *style = widget ? widget->style() : QApplication::style();
            return style->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), widget);
        }
    };
    
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc,argv);
        QListView wid;
        wid.setStyleSheet(QStringLiteral("color: red"));
        QStandardItemModel model(2,1);
        model.setData(model.index(0,0),QStringLiteral("Somebody"));
        model.setData(model.index(0,0),QStringLiteral("once Told Me"), Qt::UserRole);
        model.setData(model.index(1,0),QStringLiteral("The world"));
        model.setData(model.index(1,0),QStringLiteral("is gonna roll me"), Qt::UserRole);
        wid.setModel(&model);
        wid.setItemDelegateForRow(0, new FixTextDelegate(&wid));
        wid.setItemDelegateForRow(1, new ManualTextDelegate(&wid));
        wid.show();
        return app.exec();
    }
    


  • @VRonin said in How to draw styled text in QStyledItemDelegate:

    You can just use QStyle::drawItemText. Below I show 2 examples, one just fixes the text and uses drawControl, the other manually writes the text using drawItemText (ignore the sizeHint implementations)

    I apologize but this is not good answer for me, both examples don't do what I expect, because both require to execute: style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);.

    There is no way how to do it without that line?


Log in to reply