假设我的模型具有以下字符串的Qt :: DisplayRole

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

我想QTreeView则(实际上,任何项目视图),以使其像一个丰富的文本。取而代之的是,项目的看法使其像默认纯文本。如何实现期望的呈现


实际上,这是一个搜索结果的模型。用户输入的文本,一些文档中搜索针对文本和向用户呈现与搜索结果,其中被搜索应该比周围的文字更大胆的词语的

有帮助吗?

解决方案 2

我的回答大多是由@ 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());
}

其他提示

我想你可以使用 setItemDelegate 树视图的方法为您的树视图项目设置自定义的画家。在委托的paint方法,你可以用另外,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();
}

下面是为我工作的上述回答的组合的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):
    #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)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top