Cómo hacer que la vista de elemento vea texto enriquecido (html) en Qt

Supongamos que mi modelo tiene elementos con la siguiente cadena para Qt :: DisplayRole

blah-blah some text other blah 

Quiero que QTreeView (en realidad, cualquier vista de elemento) lo represente como un texto enriquecido. En cambio, las vistas de elementos lo muestran como un texto puro por defecto. ¿Cómo lograr el renderizado deseado?


En realidad, este es un modelo de resultados de búsqueda. El usuario ingresa un texto, se busca en algún documento con ese texto y se le presentan resultados de búsqueda, donde las palabras que se buscan deben ser más audaces que el texto circundante.

Supongo que puede usar el método setItemDelegate de la vista en árbol para configurar el pintor personalizado para sus elementos treeview. En el método de pintura del delegado, puede usar QTextDocument para cargar el texto del elemento como html y renderizarlo. Por favor, compruebe si un ejemplo a continuación podría funcionar para usted:

inicialización de treeview:

 ... // 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, "blah-blah some text other blah"); } // create custom delegate HTMLDelegate* delegate = new HTMLDelegate(); // set model and delegate to the treeview object ui->treeView->setModel(model); ui->treeView->setItemDelegate(delegate); ... 

implementación personalizada de delegates

 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->restre(); } 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()); } 

espero que esto ayude, saludos

update0 : cambia a HTMLDelegate para hacer que los icons sean visibles y el color del lápiz sea diferente para los elementos seleccionados

 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->restre(); } 

Mi respuesta está inspirada principalmente en la de @serge_gubenko. Sin embargo, se realizaron varias mejoras para que el código finalmente sea útil en mi aplicación.

 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->restre(); } 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()); } 

Aquí está la conversión PyQt de la combinación de las respuestas anteriores que funcionó para mí. Esperaría que esto funcione de forma prácticamente idéntica para PySide también.

 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.restre() 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()) 

Este está en PySide. En lugar de hacer muchos dibujos personalizados, paso el QPainter al QLabel y lo hago dibujar solo. Resaltando el código prestado de otras respuestas.

 from PySide import QtGui class TaskDelegate(QtGui.QItemDelegate): #http://doc.qt.nokia.com/4.7/qitemdelegate.html#drawDisplay #http://doc.qt.nokia.com/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) 
    Intereting Posts