Question

Supposons que mon modèle a des éléments avec la chaîne suivante pour Qt :: DisplayRole

<span>blah-blah <b>some text</b> other blah</span>

Je veux QTreeView (en fait, une vue de l'élément) pour le rendre comme un texte riche. Au lieu de cela, des vues de l'élément de rendu comme un texte pur par défaut. Comment obtenir le rendu souhaité?


En fait, c'est un modèle de résultats de recherche. L'utilisateur entre un texte, un document est recherché contre ce texte et l'utilisateur est présenté avec des résultats de recherche, où les mots recherchés doivent être plus audacieux que le texte environnant.

Était-ce utile?

La solution 2

Ma réponse est le plus souvent inspiré par celui de @ serge_gubenko. Cependant, il y avait apporté plusieurs améliorations afin que le code est enfin utile dans mon application.

class HtmlDelegate : public QStyledItemDelegate
{
protected:
    void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
    QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;
};

void HtmlDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItemV4 optionV4 = option;
    initStyleOption(&optionV4, index);

    QStyle *style = optionV4.widget? optionV4.widget->style() : QApplication::style();

    QTextDocument doc;
    doc.setHtml(optionV4.text);

    /// Painting item without text
    optionV4.text = QString();
    style->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter);

    QAbstractTextDocumentLayout::PaintContext ctx;

    // Highlighting text if item is selected
    if (optionV4.state & QStyle::State_Selected)
        ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText));

    QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &optionV4);
    painter->save();
    painter->translate(textRect.topLeft());
    painter->setClipRect(textRect.translated(-textRect.topLeft()));
    doc.documentLayout()->draw(painter, ctx);
    painter->restore();
}

QSize HtmlDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItemV4 optionV4 = option;
    initStyleOption(&optionV4, index);

    QTextDocument doc;
    doc.setHtml(optionV4.text);
    doc.setTextWidth(optionV4.rect.width());
    return QSize(doc.idealWidth(), doc.size().height());
}

Autres conseils

Je suppose que vous pouvez utiliser la méthode setItemDelegate du TreeView configurer peintre personnalisé pour vos articles TreeView. Dans la méthode de peinture du délégué, vous pouvez utiliser QTextDocument pour charger le texte de l'élément HTML et de le rendre. S'il vous plaît vérifier si un exemple ci-dessous fonctionnerait pour vous:

initialisation d'arborescence:

...
    // create simple model for a tree view
    QStandardItemModel *model = new QStandardItemModel();
    QModelIndex parentItem;
    for (int i = 0; i < 4; ++i)
    {
        parentItem = model->index(0, 0, parentItem);
        model->insertRows(0, 1, parentItem);
        model->insertColumns(0, 1, parentItem);
        QModelIndex index = model->index(0, 0, parentItem);
        model->setData(index, "<span>blah-blah <b>some text</b> other blah</span>");
    }
    // create custom delegate
    HTMLDelegate* delegate = new HTMLDelegate();
    // set model and delegate to the treeview object
    ui->treeView->setModel(model);
    ui->treeView->setItemDelegate(delegate);
...

délégué mesure mise en œuvre

class HTMLDelegate : public QStyledItemDelegate
{
protected:
    void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
    QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;
};

void HTMLDelegate::paint(QPainter* painter, const QStyleOptionViewItem & option, const QModelIndex &index) const
{
    QStyleOptionViewItemV4 options = option;
    initStyleOption(&options, index);

    painter->save();

    QTextDocument doc;
    doc.setHtml(options.text);

    options.text = "";
    options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);

    painter->translate(options.rect.left(), options.rect.top());
    QRect clip(0, 0, options.rect.width(), options.rect.height());
    doc.drawContents(painter, clip);

    painter->restore();
}

QSize HTMLDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
    QStyleOptionViewItemV4 options = option;
    initStyleOption(&options, index);

    QTextDocument doc;
    doc.setHtml(options.text);
    doc.setTextWidth(options.rect.width());
    return QSize(doc.idealWidth(), doc.size().height());
}

espère que cette aide, ce qui a trait

update0 : modifications à HTMLDelegate pour faire des icônes visibles et couleur différente stylo pour les éléments sélectionnés

void HTMLDelegate::paint(QPainter* painter, const QStyleOptionViewItem & option, const QModelIndex &index) const
{
    QStyleOptionViewItemV4 options = option;
    initStyleOption(&options, index);

    painter->save();

    QTextDocument doc;
    doc.setHtml(options.text);

    options.text = "";
    options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);

    // shift text right to make icon visible
    QSize iconSize = options.icon.actualSize(options.rect.size());
    painter->translate(options.rect.left()+iconSize.width(), options.rect.top());
    QRect clip(0, 0, options.rect.width()+iconSize.width(), options.rect.height());

    //doc.drawContents(painter, clip);

    painter->setClipRect(clip);
    QAbstractTextDocumentLayout::PaintContext ctx;
    // set text color to red for selected item
    if (option.state & QStyle::State_Selected)
        ctx.palette.setColor(QPalette::Text, QColor("red"));
    ctx.clip = clip;
    doc.documentLayout()->draw(painter, ctx);

    painter->restore();
}

Voici la conversion PyQt de la combinaison des réponses ci-dessus qui ont travaillé pour moi. J'attendre que cela fonctionne à peu près identique pour PySide ainsi.

from PyQt4 import QtCore, QtGui

class HTMLDelegate(QtGui.QStyledItemDelegate):
    def paint(self, painter, option, index):
        options = QtGui.QStyleOptionViewItemV4(option)
        self.initStyleOption(options,index)

        style = QtGui.QApplication.style() if options.widget is None else options.widget.style()

        doc = QtGui.QTextDocument()
        doc.setHtml(options.text)

        options.text = ""
        style.drawControl(QtGui.QStyle.CE_ItemViewItem, options, painter);

        ctx = QtGui.QAbstractTextDocumentLayout.PaintContext()

        # Highlighting text if item is selected
        #if (optionV4.state & QStyle::State_Selected)
            #ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText));

        textRect = style.subElementRect(QtGui.QStyle.SE_ItemViewItemText, options)
        painter.save()
        painter.translate(textRect.topLeft())
        painter.setClipRect(textRect.translated(-textRect.topLeft()))
        doc.documentLayout().draw(painter, ctx)

        painter.restore()

    def sizeHint(self, option, index):
        options = QtGui.QStyleOptionViewItemV4(option)
        self.initStyleOption(options,index)

        doc = QtGui.QTextDocument()
        doc.setHtml(options.text)
        doc.setTextWidth(options.rect.width())
        return QtCore.QSize(doc.idealWidth(), doc.size().height())

Celui-ci est en PySide. Plutôt que de faire beaucoup de dessin personnalisé, je passe le QPainter au QLabel et fais se dessiner. Code Mise en surbrillance emprunté à d'autres réponses.

from PySide import QtGui

class TaskDelegate(QtGui.QItemDelegate):
    #https://doc.qt.io/archives/qt-4.7/qitemdelegate.html#drawDisplay
    #https://doc.qt.io/archives/qt-4.7/qwidget.html#render
    def drawDisplay(self, painter, option, rect, text):
        label = QtGui.QLabel(text)

        if option.state & QtGui.QStyle.State_Selected:
            p = option.palette
            p.setColor(QtGui.QPalette.WindowText, p.color(QtGui.QPalette.Active, QtGui.QPalette.HighlightedText))

            label.setPalette(p)

        label.render(painter, rect.topLeft(), renderFlags=QtGui.QWidget.DrawChildren)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top