如何使项目视图渲染丰富(html)文本在Qt中
假设我的模型有Qt :: DisplayRolestring
<span>blah-blah <b>some text</b> other blah</span>
我想要QTreeView(实际上,任何项目视图)呈现它像一个丰富的文本。 相反,项目视图默认情况下将其呈现为纯文本。 如何实现所需的渲染?
其实这是一个search结果模型。 用户input一个文本,对该文本search一些文档,并向用户显示search结果,其中被search的单词应该比周围的文本更大胆。
我想你可以使用树视图的setItemDelegate方法为你的树视图项目设置自定义画家。 在委托的绘制方法中,您可以使用QTextDocument将项目的文本加载为html并进行渲染。 请检查下面的例子是否适合你:
树视图初始化:
... // 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); ...
自定义委托实现
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()); }
希望这有助于问候
update0 :将HTMLDelegate更改为使图标可见,并为所选项目设置不同的笔颜色
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(); }
我的答案主要是由@ serge_gubenko的启发。 不过,我们做了一些改进,以便代码在我的应用程序中最终有用。
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()); }
这是PyQt转换为我工作的上述答案的组合。 我希望这对于PySide来说也是一样的。
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())
这个是在PySide。 我没有做大量的自定义绘图,而是将QPainter传递给QLabel并绘制自己。 突出显示从其他答案借来的代码。
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)
- 在Android Studio中进行渲染时,不支持major.minor版本52.0
- Framebuffer和Renderbuffer在OpenGL中的概念和区别是什么?
- 你如何确定WPF是否使用硬件或软件渲染?
- 在Rails中,如何使用视图呈现JSON?
- 如何在Rails中呈现不同格式的部分内容?
- Swing呈现在JDK 1.8中出现中断,在JDK 1.7中正确
- 以stringforms呈现视图
- JTextFields在JPanel上的活动绘图之上,线程问题
- 无法parsingcom.android.support:appcompat-v7:22和com.android.support:recyclerview-v7:21.1.2